Ali Soleymani Roozbahani Ali Soleymani Roozbahani - 3 months ago 56
Android Question

Encoding String to UTF-8 working with JSON in android

I have a problem with converting a

String
to UTF-8.

I have tried these approaches to converting, but the result is not correct:


  1. String fname = new String(_fnameText.getText().toString().getBytes(UTF8));

  2. String fname = URLEncoder.encode(_fnameText.getText().toString(),"UTF8");



The result for the first one is like :
?????? ??????


The result for the second one is like :
%30%D%40.....


How can I convert a
String
to UTF-8 ?

This is my code :

public void signup() {
String name;
String fname;
String lname;
String password;
final Charset UTF8=Charset.forName("utf-8");
name = new String();
fname = new String(_fnameText.getText().toString().getBytes(UTF8));
lname = new String(_lnameText.getText().toString().getBytes(UTF8));
password = new String(_passwordText.getText().toString().getBytes(UTF8));
// TODO: Implement your own signup logic here.
if(name!=null && fname!=null && lname!=null && password!=null) {
if (isConnected()) {
if (validate()) {
_signupButton.setEnabled(false);
jsonSignup = new JSON_Signup(SignupActivity.this, "http://teroject.com/api/android.php", name, password);
jsonSignup.valuesForServer.add(new BasicNameValuePair("api_key", "teroapi_php_java_1395"));
jsonSignup.valuesForServer.add(new BasicNameValuePair("api_function", "register"));
jsonSignup.valuesForServer.add(new BasicNameValuePair("username", name));
jsonSignup.valuesForServer.add(new BasicNameValuePair("password", password));
jsonSignup.valuesForServer.add(new BasicNameValuePair("fname", fname));
jsonSignup.valuesForServer.add(new BasicNameValuePair("lname", lname));
jsonSignup.execute();
}
}
}else {
Toast.makeText(getApplicationContext(),"لطفا از کاراکتر های مجاز استفاده کنید",Toast.LENGTH_SHORT).show();
}

}

public JSON_Signup(Context context,String url,String username,String password){
this.context=context;
this.url=url;
this.username=username;
this.password=password;
progressDialog=new ProgressDialog(this.context);
}

@Override
protected void onPreExecute() {
progressDialog.setMessage("در حال ثبت نام لطفا صبر کنید....");
progressDialog.show();
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface arg0) {
JSON_Signup.this.cancel(true);
}
});
}

@Override
protected String doInBackground(String... params) {
try {
// Set up HTTP post
// HttpClient is more then less deprecated. Need to change to URLConnection
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 20000);
HttpConnectionParams.setSoTimeout(httpParameters, 20000);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(valuesForServer));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();

StatusLine statusLine = httpResponse.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
// Read content & Log
inputStream = httpEntity.getContent();
}else{
return null;
}
}catch (NetworkOnMainThreadException e7){
Log.i("Network on Main Thread", e7 + "");
e7.printStackTrace();
return null;
} catch(SocketTimeoutException e6){
Log.i("Connection Timeout", e6 + "");
e6.printStackTrace();
return null;
} catch (UnsupportedEncodingException e1) {
Log.i("Unsupported Encoding",e1+"");
e1.printStackTrace();
return null;
} catch (ClientProtocolException e2) {
Log.i("Client Protocol", e2 + "");
e2.printStackTrace();
return null;
} catch (IllegalStateException e3) {
Log.i("Illegal State", e3 + "");
e3.printStackTrace();
return null;
} catch (IOException e4) {
Log.i("Exception", e4 + "");
e4.printStackTrace();
return null;
}
// Convert response to string using String Builder
if(inputStream!=null) {
try {
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"), 8);
StringBuilder sBuilder = new StringBuilder();

String line = null;
while ((line = bReader.readLine()) != null) {
sBuilder.append(line + "\n");
}

inputStream.close();
result = sBuilder.toString();

} catch (Exception e) {
Log.i("Exception", e + "");
return null;
}
}else {
return null;
}
return result;
}

@Override
protected void onPostExecute(String result) {
if (result != null) {
//parse JSON data
try {
mainFile = new JSONObject(result);
success = mainFile.getString("success");
message = mainFile.getString("message");
if (success.equals("1")) {
_signupButton.setEnabled(true);
Toast.makeText(this.context, message, Toast.LENGTH_LONG).show();
if (isConnected()) {
JSON json;
json = new JSON(this.context, "http://teroject.com/api/android.php",
this.username,this.password);
json.valuesForServer.add(new BasicNameValuePair("api_key", "teroapi_php_java_1395"));
json.valuesForServer.add(new BasicNameValuePair("api_function", "login"));
json.valuesForServer.add(new BasicNameValuePair("username",this.username));
json.valuesForServer.add(new BasicNameValuePair("password",this.password));
json.execute();
}
} else if (success.equals("0")) {
Toast.makeText(this.context, message, Toast.LENGTH_LONG).show();
_signupButton.setEnabled(true);
}
this.progressDialog.dismiss();
} catch (JSONException e) {
Toast.makeText(this.context, e + "", Toast.LENGTH_SHORT).show();
_signupButton.setEnabled(true);
this.progressDialog.dismiss();
}
}else {
_signupButton.setEnabled(true);
progressDialog.dismiss();
Toast.makeText(this.context,"خطا در برقراری ارتباط",Toast.LENGTH_LONG).show();
}
}
}


Here is the Log :

08-02 01:22:59.185 1108-1159/? E/ActivityManager: Invalid thumbnail dimensions: 384x384
08-02 01:22:59.445 15868-15868/? E/chromium: [ERROR:layer_tree_host_impl.cc(2218)] Forcing zero-copy tile initialization as worker context is missing
08-02 01:23:00.349 271-822/? E/BandwidthController: [LG DATA] No such appUid: 10044
08-02 01:23:00.767 275-1078/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:00.767 275-1078/? E/audio_hw_primary: enable_snd_device: enter 2
08-02 01:23:01.683 30716-30716/? E/MusicBrowser: [MusicUtils.java:633:getSmartShareVersion()] oooooo getSmartShareVersion ERROR :: android.content.pm.PackageManager$NameNotFoundException: com.lge.smartshare
08-02 01:23:02.445 32207-32207/? E/LGDMClient: [DmNotiService.java] [onCreate()] : [153] : DmNotiService.onCreate()
08-02 01:23:03.971 275-1324/? E/audio_hw_primary: disable_snd_device: enter 2
08-02 01:23:13.001 32587-32587/com.teroject.teroject E/GMPM: GoogleService failed to initialize, status: 10, Missing an expected resource: 'R.string.google_app_id' for initializing Google services. Possible causes are missing google-services.json or com.google.gms.google-services gradle plugin.
08-02 01:23:13.001 32587-32587/com.teroject.teroject E/GMPM: Scheduler not set. Not logging error/warn.
08-02 01:23:13.042 32587-32616/com.teroject.teroject E/GMPM: Uploading is not possible. App measurement disabled
08-02 01:23:13.724 32587-32587/com.teroject.teroject E/MediaProfilesEx-JNI: register_com_lge_media_MediaProfilesEx
08-02 01:23:13.724 32587-32587/com.teroject.teroject E/MediaRecorderEx-JNI: register_com_lge_media_MediaRecorderEx
08-02 01:23:13.726 32587-32587/com.teroject.teroject E/SurfaceControlEx: register_com_lge_view_SurfaceControlEx
08-02 01:23:13.736 32587-32587/com.teroject.teroject E/MediaPlayerEx-jni: register_com_lge_view_MediaPlayerEx
08-02 01:23:17.325 32587-32587/com.teroject.teroject E/CliptrayUtils: hideClipTrayIfNeeded() TextView is focused!! hideClipTray()
08-02 01:23:19.477 2636-2636/? E/NetworkScheduler.SR: Invalid parameter app
08-02 01:23:19.477 2636-2636/? E/NetworkScheduler.SR: Invalid package name : Perhaps you didn't include a PendingIntent in the extras?
08-02 01:23:19.579 2032-4467/? E/Drive.UninstallOperation: Package still installed com.teroject.teroject
08-02 01:23:21.148 275-1078/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:21.148 275-1078/? E/audio_hw_primary: enable_snd_device: enter 2
08-02 01:23:21.577 409-409/? E/Finsky: [1] com.google.android.finsky.wear.bo.a(837): onConnectionFailed: ConnectionResult{statusCode=API_UNAVAILABLE, resolution=null, message=null}
08-02 01:23:22.539 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:23.112 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:23.293 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:24.199 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:24.565 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:24.954 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:25.744 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:26.073 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:26.273 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:26.714 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:28.023 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:28.259 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:28.445 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:28.638 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:28.835 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:29.042 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:29.275 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:29.739 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:30.509 2032-905/? E/IntentOperationSvc: Failed to instantiate Chimera operation impl, dropping operation
08-02 01:23:30.583 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:30.658 32587-32587/com.teroject.teroject E/View: hasTransientState decremented below 0: unmatched pair of setHasTransientState calls
08-02 01:23:32.265 914-914/? E/Finsky: [1] com.google.android.finsky.wear.bo.a(837): onConnectionFailed: ConnectionResult{statusCode=API_UNAVAILABLE, resolution=null, message=null}
08-02 01:23:32.958 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:33.229 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:33.823 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:34.129 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:34.336 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:34.387 2636-2636/? E/NetworkScheduler.SR: Invalid parameter app
08-02 01:23:34.387 2636-2636/? E/NetworkScheduler.SR: Invalid package name : Perhaps you didn't include a PendingIntent in the extras?
08-02 01:23:34.662 1186-1186/? E/App: [App][onCreate()] 4.40.21
08-02 01:23:34.785 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:36.379 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:36.488 32587-32587/com.teroject.teroject E/View: hasTransientState decremented below 0: unmatched pair of setHasTransientState calls
08-02 01:23:37.519 1310-1310/? E/LGDMClient: [DmNotiService.java] [onCreate()] : [153] : DmNotiService.onCreate()
08-02 01:23:37.600 271-822/? E/BandwidthController: [LG DATA] No such appUid: 10100
08-02 01:23:37.832 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:38.623 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:38.972 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:39.463 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:39.810 1310-1310/? E/LGDMClient: [DmNotiService.java] [onCreate()] : [153] : DmNotiService.onCreate()
08-02 01:23:40.283 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:40.548 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:40.749 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:41.392 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:42.272 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:42.368 32587-32587/com.teroject.teroject E/View: hasTransientState decremented below 0: unmatched pair of setHasTransientState calls
08-02 01:23:42.509 1228-1228/? E/ActivityThread: Failed to find provider info for com.facebook.katana.provider.AttributionIdProvider
08-02 01:23:42.537 1228-1267/? E/ActivityThread: Failed to find provider info for com.facebook.katana.provider.AttributionIdProvider
08-02 01:23:42.642 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:42.922 271-822/? E/BandwidthController: [LG DATA] No such appUid: 10101
08-02 01:23:42.942 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:43.205 271-822/? E/BandwidthController: [LG DATA] No such appUid: 10101
08-02 01:23:43.435 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:44.025 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:44.285 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:44.495 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:45.733 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:46.999 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:23:47.101 32587-32587/com.teroject.teroject E/View: hasTransientState decremented below 0: unmatched pair of setHasTransientState calls
08-02 01:23:47.967 1566-1566/? E/Finsky: [1] com.google.android.finsky.wear.bo.a(837): onConnectionFailed: ConnectionResult{statusCode=API_UNAVAILABLE, resolution=null, message=null}
08-02 01:23:48.401 271-822/? E/BandwidthController: [LG DATA] No such appUid: 10151
08-02 01:23:48.469 32587-32587/com.teroject.teroject E/CliptrayUtils: hideClipTrayIfNeeded() TextView is focused!! hideClipTray()
08-02 01:23:50.138 275-1324/? E/audio_hw_primary: disable_snd_device: enter 2
08-02 01:23:54.695 1310-1310/? E/LGDMClient: [DmNotiService.java] [onCreate()] : [153] : DmNotiService.onCreate()
08-02 01:23:55.483 271-822/? E/BandwidthController: [LG DATA] No such appUid: 10151
08-02 01:24:00.979 1310-1310/? E/LGDMClient: [DmNotiService.java] [onCreate()] : [153] : DmNotiService.onCreate()
08-02 01:24:01.475 32587-32587/com.teroject.teroject E/OneSignal: You must initialize OneSignal before modifying tags! Omitting this tag operation.
08-02 01:24:02.643 32587-32587/com.teroject.teroject E/CliptrayUtils: hideClipTrayIfNeeded() TextView is focused!! hideClipTray()
08-02 01:24:04.019 2636-1894/? E/CommitToConfigurationOperation: Malformed snapshot token (size):
08-02 01:24:04.045 2636-1894/? E/CommitToConfigurationOperation: Malformed snapshot token (size):
08-02 01:24:04.079 2636-1894/? E/CommitToConfigurationOperation: Malformed snapshot token (size):
08-02 01:24:04.142 271-822/? E/BandwidthController: [LG DATA] No such appUid: 10004
08-02 01:24:04.408 275-1078/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:24:04.408 275-1078/? E/audio_hw_primary: enable_snd_device: enter 2
08-02 01:24:05.356 275-1324/? E/audio_hw_primary: select_devices: enter and usecase(1)
08-02 01:24:08.505 275-1324/? E/audio_hw_primary: disable_snd_device: enter 2
08-02 01:24:10.637 271-822/? E/BandwidthController: [LG DATA] No such appUid: 10151

Answer

The correct way to convert a String to UTF-8 is to call getBytes() by itself:

byte[] fname = _fnameText.getText().toString().getBytes(UTF8);

You are doing that fine, but then you are doing other things with that output that are not fine.

Your first example is wrong because you are converting the UTF-8 bytes back to a String using Java's default charset, which is clearly not UTF-8 on your system.

Your second example is wrong because you are manually URL-encoding the UTF-8 bytes at the wrong stage of your HTTP logic.

You should not be converting your individual input strings to UTF-8 at all. Build up your HTTP request values as needed, and then let UrlEncodedFormEntity handle the conversion to UTF-8 when posting over HTTP. UrlEncodedFormEntity() has two constructors, one of which takes an encoding as an input parameter, but you are not using that constructor.

Try something more like this:

public void signup() {
    String name = new String();
    String fname = _fnameText.getText().toString();
    String lname = _lnameText.getText().toString();
    String password = _passwordText.getText().toString();
    // TODO: Implement your own signup logic here.
    if(name!=null && fname!=null && lname!=null && password!=null) {
        if (isConnected()) {
            if (validate()) {
                _signupButton.setEnabled(false);
                jsonSignup = new JSON_Signup(SignupActivity.this, "http://teroject.com/api/android.php", name, password);
                jsonSignup.valuesForServer.add(new BasicNameValuePair("api_key", "teroapi_php_java_1395"));
                jsonSignup.valuesForServer.add(new BasicNameValuePair("api_function", "register"));
                jsonSignup.valuesForServer.add(new BasicNameValuePair("username", name));
                jsonSignup.valuesForServer.add(new BasicNameValuePair("password", password));
                jsonSignup.valuesForServer.add(new BasicNameValuePair("fname", fname));
                jsonSignup.valuesForServer.add(new BasicNameValuePair("lname", lname));
                jsonSignup.execute();
            }
        }
    }else {
        Toast.makeText(getApplicationContext(), "لطفا از کاراکتر های مجاز استفاده کنید", Toast.LENGTH_SHORT).show();
    }

}

public JSON_Signup(Context context, String url, String username, String password){
        this.context=context;
        this.url=url;
        this.username=username;
        this.password=password;
        valuesForServer=new List<BasicNameValuePair>();
        progressDialog=new ProgressDialog(this.context);
    }

    @Override
    protected void onPreExecute() {
        progressDialog.setMessage("در حال ثبت نام لطفا صبر کنید....");
        progressDialog.show();
        progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            public void onCancel(DialogInterface arg0) {
                JSON_Signup.this.cancel(true);
            }
        });
    }

    @Override
    protected String doInBackground(String... params) {
        try {
            // Set up HTTP post
            // HttpClient is more then less deprecated. Need to change to URLConnection
            HttpParams httpParameters = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParameters, 20000);
            HttpConnectionParams.setSoTimeout(httpParameters, 20000);
            DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new UrlEncodedFormEntity(valuesForServer, "utf-8"));
            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();

            StatusLine statusLine = httpResponse.getStatusLine();
            if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                // Read content & Log
                inputStream = httpEntity.getContent();
            }else{
                return null;
            }
        }catch (NetworkOnMainThreadException e7){
            Log.i("Network on Main Thread", e7 + "");
            e7.printStackTrace();
            return null;
        } catch(SocketTimeoutException e6){
            Log.i("Connection Timeout", e6 + "");
            e6.printStackTrace();
            return null;
        } catch (UnsupportedEncodingException e1) {
            Log.i("Unsupported Encoding",e1+"");
            e1.printStackTrace();
            return null;
        } catch (ClientProtocolException e2) {
            Log.i("Client Protocol", e2 + "");
            e2.printStackTrace();
            return null;
        } catch (IllegalStateException e3) {
            Log.i("Illegal State", e3 + "");
            e3.printStackTrace();
            return null;
        } catch (IOException e4) {
            Log.i("Exception", e4 + "");
            e4.printStackTrace();
            return null;
        }
        // Convert response to string using String Builder
        if(inputStream!=null) {
            try {
                BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"), 8);
                StringBuilder sBuilder = new StringBuilder();

                String line = null;
                while ((line = bReader.readLine()) != null) {
                    sBuilder.append(line + "\n");
                }

                inputStream.close();
                result = sBuilder.toString();

            } catch (Exception e) {
                Log.i("Exception", e + "");
                return null;
            }
        }else {
            return null;
        }
        return result;
    }

    @Override
    protected void onPostExecute(String result) {
        if (result != null) {
            //parse JSON data
            try {
                mainFile = new JSONObject(result);
                success = mainFile.getString("success");
                message = mainFile.getString("message");
                if (success.equals("1")) {
                    _signupButton.setEnabled(true);
                    Toast.makeText(this.context, message, Toast.LENGTH_LONG).show();
                    if (isConnected()) {
                        JSON json = new JSON(this.context, "http://teroject.com/api/android.php", this.username, this.password);
                        json.valuesForServer.add(new BasicNameValuePair("api_key", "teroapi_php_java_1395"));
                        json.valuesForServer.add(new BasicNameValuePair("api_function", "login"));
                        json.valuesForServer.add(new BasicNameValuePair("username", this.username));
                        json.valuesForServer.add(new BasicNameValuePair("password", this.password));
                        json.execute();
                    }
                } else if (success.equals("0")) {
                    Toast.makeText(this.context, message, Toast.LENGTH_LONG).show();
                    _signupButton.setEnabled(true);
                }
                this.progressDialog.dismiss();
            } catch (JSONException e) {
                Toast.makeText(this.context, e + "", Toast.LENGTH_SHORT).show();
                _signupButton.setEnabled(true);
                this.progressDialog.dismiss();
            }
        }else {
            _signupButton.setEnabled(true);
            progressDialog.dismiss();
            Toast.makeText(this.context,"خطا در برقراری ارتباط",Toast.LENGTH_LONG).show();
        }
    }
}

You did not show the code for JSON.execute(), but the concept is the same. Collect the HTTP values as normal String values, and then let UrlEncodedFormEntity convert the values to UTF-8 when posting the final HTTP request.

Comments