I am trying to retrieve some data from my database in my android app, but some special characters are sent incorrectly. The data is actually firstly sent from my app, stored, and then retrieved. When I send it, the data registers in a correct way, but when it comes about retrieving there seem to be a coding/decoding problem.
To store the data correctly, I used mysqli_set_charset($conn, 'utf8'); command, so the data Situație 4 is stored as it was sent.
PHP code to send the data:
$stmt->bind_result($id, $latitudine, $longitudine, $tip_problema, $data_ora, $ora_catalogare, $validare, $grad_incredere);
while($stmt->fetch()) {
$locatie[] = array (
"id_alerta"=>$id,
"latitudine"=>$latitudine,
"longitudine"=>$longitudine,
"tip_problema"=>$tip_problema,
"data_ora"=>$data_ora,
"ora_catalogare"=>$ora_catalogare,
"stare_problema"=>$validare,
"grad_incredere"=>$grad_incredere
);
$response['error'] = false;
$response['message'] = 'Alerte reimprospatate';
$response['locatie']= $locatie;
}
The infos I need are stored in the $locatie, so I could get the JSON response on my app.
The app code enterpreting JSON response:
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//hiding the progressbar after completion
try {
//converting response to json object
JSONObject obj = new JSONObject(s);
//if no error in response
if (!obj.getBoolean("error")) {
Toast.makeText(getApplicationContext(), obj.getString("message"), Toast.LENGTH_SHORT).show();
JSONArray locatieArray = obj.getJSONArray("locatie");
for (int i = 0; i < locatieArray.length(); i++) {
JSONObject locatie = locatieArray.getJSONObject(i);
// check latitudine and longitudine is not null and if not null then cast these values and call the addMarker() method.
if (!locatie.isNull("latitudine") && !locatie.isNull("longitudine")) {
latitudine_sql = Double.valueOf(locatie.getString("latitudine"));
longitudine_sql = Double.valueOf(locatie.getString("longitudine"));
tip_problema_sql = locatie.getString("tip_problema");
id = locatie.getString("id_alerta");
data_ora_raportare = locatie.getString("data_ora");
stare_alarma = locatie.getString("stare_problema");
data_ora_ack = locatie.getString("ora_catalogare");
grad_incredere = locatie.getString("grad_incredere");
addMarker(latitudine_sql, longitudine_sql);
}
}
} else {
Toast.makeText(getApplicationContext(), "Some error occurred", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here comes the tricky part. The json response looks like:
{
"error": false,
"message": "Alerte reimprospatate",
"locatie": [{
"id_alerta": 43,
"latitudine": "37.41593630609526",
"longitudine": "-122.09065474569798",
"tip_problema": "Situa\u021bie 4",
"data_ora": "2020-01-14 15:44:37",
"ora_catalogare": null,
"stare_problema": "Nevalidat",
"grad_incredere": 65.75
}]
}
Even though in the database the tip_problema column has Situație 4 stored, when it is sent over to the app it transforms in Situa\u021bie 4.
To establish a connection I use a RequestHandler:
public class RequestHandler {
public String sendPostRequest(String requestURL, HashMap<String, String> postDataParams) {
URL url;
StringBuilder sb = new StringBuilder();
try {
url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode = conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
sb = new StringBuilder();
String response;
while ((response = br.readLine()) != null) {
sb.append(response);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for (Map.Entry<String, String> entry : params.entrySet()) {
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}
}
Where I have set everywhere the UTF-8 collation. Any advice would be very much appreciated!
UPDATE:
I have added UTF-8 to BufferReader on the InputStream but the response is the same.
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));
UPDATE: After reinstalling the app, even though the response it's the same Situa\u021bie 4 the app seems to understands that the message refers to Situație 4 thus it's working properly now.
\u021bis simply a way to encode the special characterțin JSON here - there is nothing inherently wrong with that. Your android application should be able to deal with that, if it is handling JSON properly. You have not shown us where you are actually creating this JSON - in PHP, you could use the optionJSON_UNESCAPED_UNICODEto havejson_encodenot encode Unicode characters this way. But that probably has a potential to break things in some other place then.echo json_encode($response);to create theJSON