アプリケーションがクラッシュしたときにGCMからメッセージを初めて受信すると、後続のメッセージはエラーなしで処理されます。
-
12-12-2019 - |
質問
私のエミュレータには2つのアプリケーションがインストールされています。「マネージャ」アプリはGCMにメッセージを送信します。「Scheduler」というその他のアプリはメッセージを受け取り、ユーザーに通知を表示します。
エミュレータ上で同時に両方のアプリケーションを実行している場合、Managerアプリは大丈夫です。ただし、SchedulerアプリはGCMIntentService
プロセスの後にクラッシュします。これは最初のメッセージでのみ発生します。残りのすべてのメッセージはアプリケーションがクラッシュしなくても処理されます。
LOGCATでエラーは印刷されません。
質問
- GCMintentServiceの例外処理はありますか?
- アプリが表示されず、GcmintentServiceがアクティビティを開く機能を呼び出します。これはプログラムをクラッシュすることができますか?
- 同時にエミュレータ上で実行されている2つのアプリがある場合は、エミュレータの問題になることができますか?
これはGCMintentseriveコードです:
./** * {@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); } } } }
解決
この問題を作成したコードには2つの問題がありました。
-
私は、event_id_from_serverがアプリケーションでNULLまたは空の場合にチェックされた条件はありません。
-
GCMにメッセージを送信すると、NULLまたは「」にしてはいけません。それはサービスをクラッシュします。 だから私はそれらに関連付けられていないメッセージのためにPHPでこの条件を作成する必要がありました:
(!$ 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' ); }
所属していません StackOverflow