-3

I have a chat app that tries to sign someone in to a server. The code for the sign in is implemented using AsyncTask. The problem is that during the sign in process and there is a network loss, the app crashes despite all the try... catch statements i used. pls how can I handle this gracefully by informing the user for the network loss instead of application crash.

I checked for network before calling the asynctask, but what I want to avoid is when you are in the middle of the process and there is a sudden network loss

this is part of the codes

protected String doInBackground(String... args) {
        try {

        DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(LOGIN_URL);
                httpPost.setEntity(new UrlEncodedFormEntity(params));

                HttpResponse httpResponse = httpClient.execute(httpPost);

                int statusCode=httpResponse.getStatusLine().getStatusCode();

                if(statusCode!=HttpStatus.SC_OK){

                    Log.d("latestchat", "Connection Error");

                    Toast.makeText(Login.this, "Error in Network Connection\n ", Toast.LENGTH_LONG).show();
                    return null;
                }

                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();


          if(is!=null){
       BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            // Declare a string builder to help with the parsing.
            StringBuilder sb = new StringBuilder();
            // Declare a string to store the JSON object data in string form.
            String line = null;

            // Build the string until null.
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }

            // Close the input stream.
            is.close();
            // Convert the string builder data to an actual string.
            json = sb.toString();
            jObj = new JSONObject(json);


          }

        } catch (JSONException e) {
            Log.d("latestchat", "JSon error: "+e.toString());

            Toast.makeText(Login.this, "Error in Network Connection\n "+e.getMessage(), Toast.LENGTH_LONG).show();

        }
        catch (UnsupportedEncodingException e) {
            Toast.makeText(Login.this, "Unsupported Encoding ", Toast.LENGTH_LONG).show();
        } catch (ClientProtocolException e) {
            Toast.makeText(Login.this, "Protocol not supported ", Toast.LENGTH_LONG).show();

        } catch (IOException e) {
            Toast.makeText(Login.this, "Error connecting to Server ", Toast.LENGTH_LONG).show();
            Log.e("latestchat", "Error connecting to Server " + e.toString());

        }
        catch (Exception e) {
            Toast.makeText(Login.this, "Error connecting to Server ", Toast.LENGTH_LONG).show();
            Log.e("latestchat", "Error connecting to Server " + e.toString());

        }
        return null;

    }

this is the logcat

11-06 13:03:17.169 E/AndroidRuntime(16149):     at com.example.latestchat.Login$AttemptLogin.doInBackground(Login.java:303)
11-06 13:03:17.169 E/AndroidRuntime(16149):     at com.example.latestchat.Login$AttemptLogin.doInBackground(Login.java:1)
11-06 13:05:58.249 E/AndroidRuntime(16405):     at com.example.latestchat.Login$AttemptLogin.doInBackground(Login.java:303)
11-06 13:05:58.249 E/AndroidRuntime(16405):     at com.example.latestchat.Login$AttemptLogin.doInBackground(Login.java:1)
11-06 13:05:59.329 E/WindowManager(16405): Activity com.example.latestchat.Login has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@407cb440 that was originally added here
11-06 13:05:59.329 E/WindowManager(16405): android.view.WindowLeaked: Activity com.example.latestchat.Login has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@407cb440 that was originally added here
11-06 13:05:59.329 E/WindowManager(16405):  at com.example.latestchat.Login$AttemptLogin.onPreExecute(Login.java:186)
11-06 13:05:59.329 E/WindowManager(16405):  at com.example.latestchat.Login.newLogin(Login.java:171)
11-06 13:05:59.329 E/WindowManager(16405):  at com.example.latestchat.Login.logIn(Login.java:120)
11-06 13:07:20.429 E/AndroidRuntime(16573):     at com.example.latestchat.Login$AttemptLogin.doInBackground(Login.java:303)
11-06 13:07:20.429 E/AndroidRuntime(16573):     at com.example.latestchat.Login$AttemptLogin.doInBackground(Login.java:1)
11-06 13:07:21.119 E/WindowManager(16573): Activity com.example.latestchat.Login has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@407c9468 that was originally added here
11-06 13:07:21.119 E/WindowManager(16573): android.view.WindowLeaked: Activity com.example.latestchat.Login has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@407c9468 that was originally added here
11-06 13:07:21.119 E/WindowManager(16573):  at com.example.latestchat.Login$AttemptLogin.onPreExecute(Login.java:186)
11-06 13:07:21.119 E/WindowManager(16573):  at com.example.latestchat.Login.newLogin(Login.java:171)
11-06 13:07:21.119 E/WindowManager(16573):  at com.example.latestchat.Login.logIn(Login.java:120)
fortech
  • 3
  • 1
  • 3

5 Answers5

3

You are doing a UI operation (Toast.makeText()) inside doInBackground(). This is wrong because the thread that executes doInBackground() is not the main (UI) thread.

Toast.makeText() should be called in onPostExecute() or onCancelled(). Please rework your code to accomplish that.

My suggestion is to perform cancel() inside doInBackground() if a network exception is caught, so onCancelled() will be called next instead of onPostExecute(), and then perform Toast.makeText() inside onCancelled().

Piovezan
  • 3,215
  • 1
  • 28
  • 45
1

You can check if network is available first. Here is a method i have used in some apps :

public boolean isNetworkAvailable() {
    return  isNetworkAvailable(false);
}

public boolean isNetworkAvailable(boolean withToast) {
        ConnectivityManager connectivityManager = (ConnectivityManager) this
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager
                .getActiveNetworkInfo();
        if (activeNetworkInfo == null) {
            if (withToast) {
                Toast.makeText(getApplicationContext(),
                        R.string.checkYourConnexion, Toast.LENGTH_LONG).show();
            }
            return false;
        } else
            return activeNetworkInfo.isConnectedOrConnecting();
    }
S.Thiongane
  • 6,883
  • 3
  • 37
  • 52
0

You need to check for the network is available or not before executing webservice request.

If the network is lost after the w/s request you should catch the timeout exception and show the user appropriate message.

PgmFreek
  • 6,374
  • 3
  • 36
  • 47
0

Use the following function before making the call, whether network connection is present or not.

private boolean isNetworkConnected(Context context)
{
    ConnectivityManager connectivityManager =     (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null;   
}

Here, context is activity's context you will be using.

Bette Devine
  • 1,196
  • 1
  • 9
  • 23
0

a common way to aviod app crash

Android development is most afraid of the crash, the test no problem, released on the crash, only through the emergency release hotfix to solve, but the time to prepare the hotfix may be very long, resulting in this time the user experience is very poor, android can pass Set Thread.setDefaultUncaughtExceptionHandler to catch all threads of the exception, but the main thread throws an exception will still cause the activity flashes, app process restart. Use Cockroach can guarantee that no matter how abnormal activities will not flash, app process will not restart.

https://github.com/android-notes/Cockroach/blob/master/README_en.md