0

I've this code, I want to have two different action, I want to show one classic notification to open MainActivity, and another notification to do LogoutTask, but I've this java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

I show you, my NotificationBuilder, AsyncTask and error.

NOTIFICATION METHOD

private void sendNotification(final String message) {
    if (!message.contains("password")) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_kleim_letter)
                .setContentTitle(TITLE_NAME)
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        Random random = new Random();
        int m = random.nextInt(9999 - 1000) + 1000;
        notificationManager.notify(m, notificationBuilder.build());
    } else {
        DoLogoutTask doLogoutTask = new DoLogoutTask(getBaseContext());
        doLogoutTask.execute();
        Intent intent = new Intent(MyGcmListenerService.this, Login.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(MyGcmListenerService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(MyGcmListenerService.this)
                .setSmallIcon(R.drawable.ic_stat_kleim_letter)
                .setContentTitle(TITLE_NAME)
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notificationBuilder.build());
    }
}

ASYNCTASK

public class DoLogoutTask extends AsyncTask<Void, Void, Boolean> {
SoapPrimitive resultString;
String response;
SharedPreferences mSharedPreferences;
SharedPreferences.Editor editor;
Context context;
ProgressDialog progressDialog;
public DoLogoutTask(Context context) {
    this.context = context;
    this.progressDialog = new ProgressDialog(context, R.style.progress_dialog_kleim);
}
@Override
protected void onPreExecute() {
    this.progressDialog.show();
    this.progressDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
    this.progressDialog.setCancelable(false);
    this.progressDialog.getWindow().setGravity(Gravity.BOTTOM);
    this.progressDialog.setIndeterminate(true);
}
@Override
protected Boolean doInBackground(Void... params) {
    return doLogout();
}
@Override
protected void onPostExecute(Boolean result) {
    if (progressDialog != null && progressDialog.isShowing())
        progressDialog.dismiss();
}
public Boolean doLogout() {
    Boolean isLoggedOut = null;
    mSharedPreferences = context.getSharedPreferences(PreferencesUtility.MYPREFERENCES, Context.MODE_PRIVATE);
    String URL = URL;
    String METHOD = METHOD;
    String NAMESPACE = NAMESPACE;
    String SOAP_ACTION = ACTION;
    String idCliente = mSharedPreferences.getString(PreferencesUtility.IDCLIENTE, PreferencesUtility.VALUENOTFOUND);
    String regid = mSharedPreferences.getString(PreferencesUtility.REGID, PreferencesUtility.VALUENOTFOUND);
    JSONObject parent = new JSONObject();
    JSONObject logout = new JSONObject();
    JSONArray jsonArray = new JSONArray();
    try {
        logout.put("idCliente", idCliente);
        logout.put("regid", regid);
        parent.put("cliente", jsonArray);
        jsonArray.put(logout);
        String parentString = parent.toString();
        PropertyInfo paramPI = new PropertyInfo();
        paramPI.setName("infoCliente");
        paramPI.setValue(parentString);
        paramPI.setType(String.class);
        SoapObject request = new SoapObject(NAMESPACE, METHOD);
        request.addProperty(paramPI);
        SoapSerializationEnvelope soapSerializationEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        soapSerializationEnvelope.dotNet = true;
        soapSerializationEnvelope.setOutputSoapObject(request);
        HttpTransportSE transportSE = new HttpTransportSE(URL);
        transportSE.call(SOAP_ACTION, soapSerializationEnvelope);
        resultString = (SoapPrimitive) soapSerializationEnvelope.getResponse();
        response = resultString.toString();
        isLoggedOut = !response.contains("error");
    } catch (JSONException e) {
        e.printStackTrace();
    } catch (HttpResponseException e) {
        e.printStackTrace();
    } catch (SoapFault soapFault) {
        soapFault.printStackTrace();
    } catch (XmlPullParserException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return isLoggedOut;
    }
}

ERROR

12-10 11:09:53.486 19138-19390/it.penta.kleim E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #3 Process: it.penta.kleim, PID: 19138 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() at android.os.Handler.(Handler.java:200) at android.os.Handler.(Handler.java:114) at android.app.Dialog.(Dialog.java:119) at android.app.AlertDialog.(AlertDialog.java:200) at android.app.AlertDialog.(AlertDialog.java:196) at android.app.ProgressDialog.(ProgressDialog.java:82) at it.penta.kleim.sixteen.retro_asynctasks.DoLogoutTask.(DoLogoutTask.java:44) at it.penta.kleim.sixteen.retro_gcm.MyGcmListenerService.sendNotification(MyGcmListenerService.java:107) at it.penta.kleim.sixteen.retro_gcm.MyGcmListenerService.onMessageReceived(MyGcmListenerService.java:75) at com.google.android.gms.gcm.GcmListenerService.zzq(Unknown Source) at com.google.android.gms.gcm.GcmListenerService.zzp(Unknown Source) at com.google.android.gms.gcm.GcmListenerService.zzo(Unknown Source) at com.google.android.gms.gcm.GcmListenerService.zza(Unknown Source) at com.google.android.gms.gcm.GcmListenerService$1.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818)

kAnGeL
  • 743
  • 1
  • 5
  • 8

1 Answers1

0

Your sendNotification method is called by a Thread in a thread pool executing onMessageReceived, so from there you cannot touch views. In order to touch views, you should get an Handler from the main thread (you can use Looper.getMainLooper()). Please check http://developer.android.com/training/multiple-threads/communicate-ui.html

Here a quick sample:

Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
    @Override
    public void run() {
        //do stuff on the main thread
    }
});

You should move everything related to the dialog inside the run() method

iLRedEiMAtTi
  • 141
  • 1
  • 3
  • I know this solution after I read this Exception, but please, can you show me an example on my code? You are italian like me I suppose, please AIUTAMI! :) – kAnGeL Dec 10 '15 at 11:20
  • I updated the answer with a quick sample... you should move everything touching the views into the run method of the handler. However, I don't know if the progress dialog is going to work without an activity... try it :) – iLRedEiMAtTi Dec 11 '15 at 10:02