O aplicativo trava ao receber uma mensagem do GCM pela primeira vez. As mensagens subsequentes são processadas sem erros

StackOverflow https://stackoverflow.com//questions/12684361

Pergunta

Tenho dois aplicativos instalados no meu emulador.O aplicativo “gerente” envia uma mensagem ao GCM.O outro aplicativo chamado “agendador” recebe a mensagem e exibe uma notificação ao usuário.

Quando tenho os dois aplicativos em execução ao mesmo tempo no emulador, o aplicativo gerenciador funciona bem.No entanto, o aplicativo agendador falha após GCMIntentService processos onMessage(); Isso só acontece na primeira mensagem.Todas as mensagens restantes são processadas sem que o aplicativo trave.

Nenhum erro é impresso no logcat.

Questões

  1. Existe tratamento de exceções para GCMIntentService?
  2. Se o aplicativo não estiver visível e o GCMIntentService chamar uma função para abrir uma atividade.Isso pode travar o programa?
  3. Se eu tiver dois aplicativos em execução no emulador ao mesmo tempo, isso pode ser um problema com o emulador?

Aqui está o código GCMIntentServive:

/**
 * {@link IntentService} responsible for handling GCM messages.
 */
public class GCMIntentService extends GCMBaseIntentService {
    @SuppressWarnings("hiding")
    private static final String TAG = "GCMIntentService";
    // Request code
    public static final int CUSTOM_REQUEST_CODE_ENTER_TEXT = 666;

    public GCMIntentService() {
        super(SENDER_ID);
    }

    @Override
    protected void onRegistered(Context context, String registrationId) {
        Log.i(TAG, "Device registered: " + "regId = " + registrationId);
      //  displayMessage(context, getString(R.string.gcm_registered));
        ServerUtilities.register(context, registrationId);

        displayError(context, "Device registered for Notifications from Anime Convention");
        System.out.println("Device registered: " + "regId = " + registrationId);
    }

    @Override
    protected void onUnregistered(Context context, String registrationId) {
        Log.i(TAG, "Device unregistered");
       // displayMessage(context, getString(R.string.gcm_unregistered));
        if (GCMRegistrar.isRegisteredOnServer(context)) {
            ServerUtilities.unregister(context, registrationId);
            System.out.println("Device Unregistered: " + "regId = " + registrationId);
        } else {
            // This callback results from the call to unregister made on
            // ServerUtilities when the registration to the server failed.
            Log.i(TAG, "Ignoring unregister callback");
        }
    }

    @Override
    protected void onMessage(Context context, Intent intent) {
        Log.i(TAG, "Received message");
        //String message = getString(R.string.gcm_message);

        System.out.println("onMessage: ");


        Bundle extras = intent.getExtras(); 

               String message =extras.getString("message");
               String event_id_from_server =extras.getString("server_id");
           //    displayMessage(context, message);
                generateNotification(context, message);
                saveMsg(message);    

                System.out.println("server id is "+ event_id_from_server);

                updateLocalDatabase(event_id_from_server);
        }


    @Override
    protected void onDeletedMessages(Context context, int total) {
        Log.i(TAG, "Received deleted messages notification");
        String message = getString(R.string.gcm_deleted, total);
       // displayMessage(context, message);
        // notifies user
        generateNotification(context, message);
    }

    @Override
    public void onError(Context context, String errorId) {
        Log.i(TAG, "Received error: " + errorId);

        if(errorId.equals("ACCOUNT_MISSING")){


        String error="Anime Convention Scheduler was unable to register your device for notifications. You need to add a GMAIL account to the phone inorder to use this service. Then use the Options Menu to register";

        displayError(context, error);
        displayMessage(context, error);
        }


     // save using saved preferences than display.
        if(errorId.equals("SERVICE_NOT_AVAILABLE")){

            String error="Google Cloud Messageing Service is not currently available";

            displayError(context, error);
        }


        // save using saved preferences than display.
        if(errorId.equals("AUTHENTICATION_FAILED")){
            String error="Google Cloud Messageing did not recognized your password. Please re-enter your password for your GMAIL account";
            displayError(context, error);
        }

        // save using saved preferences than display.
        if(errorId.equals("PHONE_REGISTRATION_ERROR") || errorId.equals("INVALID_PARAMETERS")){

            String error="Your phone does not support Google Cloud Messageing. You will not receive notifications from Anime Convention";
            displayError(context, error);
        }
    }

    @Override
    protected boolean onRecoverableError(Context context, String errorId) {
        // log message
        Log.i(TAG, "Received recoverable error: " + errorId);
     //   displayMessage(context, getString(R.string.gcm_recoverable_error,               errorId));

        return super.onRecoverableError(context, errorId);
    }

    /**
     * Issues a notification to inform the user that server has sent a message.
     */
    private static void generateNotification(Context context, String message) {
        int icon = R.drawable.icon;
        long when = System.currentTimeMillis();
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notification = new Notification(icon, message, when);
        String title = context.getString(R.string.app_name);
        Intent notificationIntent = new Intent(context, TabBarExample.class);
        // set intent so it does not start a new activity
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
        notification.setLatestEventInfo(context, title, message, intent);
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        notificationManager.notify(0, notification);
    }

    private String handleMessage(Intent intent) {
        String id = intent.toString();
        String message = null;
        try {
            JSONObject json = new JSONObject(id);
             message = json.getString("message_id");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return message;
    }

    public void saveMsg(String msg) {
        boolean worked = true;
        try {
            NotificationsDatabase entry = new NotificationsDatabase(GCMIntentService.this);
            entry.open();
            java.util.Date date= new java.util.Date();
             Timestamp x = new Timestamp(date.getTime());

            String timeStamp=x.toLocaleString();
            entry.createEntry(msg,timeStamp);

            entry.close();

            NoteAdapter note = null;
            note.notifyDataSetChanged();

            NewsRowAdapter nra  = null;
            nra.notifyDataSetChanged();

            AlertAdapter aa=null;
            aa.notifyDataSetChanged();
        } catch (Exception e) {
            worked = false;
            String error = e.toString();
            System.out.println(error);
        } finally {
            if (worked) {
            }
        }
    }
    @Override
    public void onDestroy() {
        GCMRegistrar.onDestroy(GCMIntentService.this.getApplicationContext());
        super.onDestroy();
    }

    public void updateLocalDatabase(String serverId){

        List<Alerts> listAlerts;

        int server_id=Integer.parseInt(serverId);

        DatabaseSqlite entry = new DatabaseSqlite (GCMIntentService.this);
        entry.open();
        listAlerts = entry.getData();       
        entry.close();

        int alerts=listAlerts.size();


        for (int i = 0; i < alerts; i++) {
            Alerts item = listAlerts.get(i);

        int remote_id =item.getRemoteServerId();
        String eventName=item.getEventName();
        int local_id=item.getRowId();

        if(server_id ==remote_id){

            //update database with new info

            // Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag
            Intent intent = new Intent(GCMIntentService.this, UpdateLocalDatabase.class);
            intent.putExtra("server_id", server_id);
            intent.putExtra("local_id", local_id);
            intent.putExtra("event_name", eventName);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            startActivity(intent);
            }
        }                   
    }
}
Foi útil?

Solução

Houve dois problemas com o código que criaram esse problema.

  1. Não tive uma condição que verificasse se event_id_from_server estava nulo ou vazio na aplicação.

  2. Ao enviar mensagens para o GCM, elas não devem ser nulas ou "".Isso trava o serviço.Então precisei criar essa condição no php para mensagens que não tinham um id associado a elas:

    if(!$id || $id==""){

        $fields = 
    array(
    'registration_ids' => $registrationIDs, 
    'data' => array("message" => $message), 
    'delay_while_idle'=> false,
    'collapse_key'=>'core_update'
    );
    
    
    
    }else{
    
    $fields = 
    array(
    'registration_ids' => $registrationIDs, 
    'data' => array("message" => $message,"server_id"=>$id), 
    'delay_while_idle'=> false,
    'collapse_key'=>'core_update'
    );
    
    }
    
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top