2

エミュレータに 2 つのアプリケーションがインストールされています。「マネージャー」アプリはメッセージを GCM に送信します。「スケジューラ」と呼ばれる別のアプリがメッセージを受信し、ユーザーに通知を表示します。

エミュレーターで両方のアプリケーションを同時に実行すると、マネージャー アプリは正常に動作します。GCMIntentServiceただし、プロセスの後にスケジューラ アプリがクラッシュしonMessage();ます。これは最初のメッセージでのみ発生します。残りのすべてのメッセージは、アプリケーションがクラッシュすることなく処理されます。

logcat にエラーは出力されません。

質問

  1. GCMIntentService の例外処理はありますか?
  2. アプリが表示されておらず、GCMIntentService が関数を呼び出してアクティビティを開く場合。これによりプログラムがクラッシュする可能性がありますか?
  3. エミュレーターで同時に 2 つのアプリを実行している場合、エミュレーターに問題がある可能性はありますか?

GCMIntentServe コードは次のとおりです。

/**
 * {@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);
            }
        }                   
    }
}
4

1 に答える 1

0

この問題を引き起こしたコードには 2 つの問題がありました。

  1. アプリケーションで event_id_from_server が null か空かをチェックする条件がありませんでした。

  2. Message を GCM に送信するときは、null または "" であってはなりません。それはサービスをクラッシュさせます。そのため、関連付けられた ID を持たないメッセージに対して、php でこの条件を作成する必要がありました。

    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'
    );
    
    }
    
于 2012-10-02T13:13:11.217 に答える