BroadcastReceiver试图在非有序广播奇怪错误期间返回结果

时间:2015-06-01 08:13:33

标签: android broadcastreceiver

即使我没有发送推送通知,第一次启动应用时也会发生此错误:

 BroadcastReceiver trying to return result during a non-ordered broadcast
        java.lang.RuntimeException: BroadcastReceiver trying to return result during a non-ordered broadcast
                at android.content.BroadcastReceiver.checkSynchronousHint(BroadcastReceiver.java:799)
                at android.content.BroadcastReceiver.setResultCode(BroadcastReceiver.java:565)
                at com.pushnotification.GcmBroadcastReceiver.onReceive(GcmBroadcastReceiver.java:17)
                at android.app.ActivityThread.handleReceiver(ActivityThread.java:2712)
                at android.app.ActivityThread.access$1700(ActivityThread.java:144)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:155)
                at android.app.ActivityThread.main(ActivityThread.java:5696)
                at java.lang.reflect.Method.invoke(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:372)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

BroadcastReceiver的代码:

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Explicitly specify that GcmIntentService will handle the intent.
        ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());

        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, (intent.setComponent(comp)));

        /* the crash is pointing to this line */
        setResultCode(Activity.RESULT_OK);
    }
}

在IntentService中实现以下代码后,错误开始出现(在应用启动时也没有调用)。但也不是每一次,I.E。从Android Studio卸载并运行应用程序后,有时会发生错误,有时它不会。

BroadcastReceiver receiver;
public void DownloadListener(final String ZipFile) {
  receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();

      if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
        long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);

        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(downloadReference);
        Cursor c = downloadManager.query(query);

        if (c.moveToFirst()) {
          int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
          if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
            DismissProgressDialog();
            ShowProgress("Almost Done", "Unzipping And Installing Database", pd.STYLE_SPINNER);
          }
        }
      }
    }
  };

  context.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}

在清单中:

<receiver
  android:name="com.pushnotification.GcmBroadcastReceiver"
  android:permission="com.google.android.c2dm.permission.SEND" >
  <intent-filter>
    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    <category android:name="com.geovision.ffmsnativeprototype" />
  </intent-filter>
</receiver>

<service android:name=".WebServiceCommunication.SystemDatabaseService" />

根据another question的答案建议注释掉setResultCode(Activity.RESULT_OK);行后,推送通知的IntentService会收到包含此内容的通知

From-google.com/iid-Title-null-Message-null-ExtraData-null

我的情况与Weird push message received on app start

相同

2 个答案:

答案 0 :(得分:4)

根据答案https://stackoverflow.com/a/30508934/1950784

这是一个谷歌相关的功能,这不是什么大问题,可以编程过滤。

@Override
    protected void onHandleIntent(Intent intent)     //RECEIVE THE PUSHNOTIFICATION
    {

        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        // The getMessageType() intent parameter must be the intent you received
        // in your BroadcastReceiver.
        String messageType = gcm.getMessageType(intent);

        if (!extras.isEmpty()) {  // has effect of unparcelling Bundle
            /*
             * Filter messages based on message type. Since it is likely that GCM
             * will be extended in the future with new message types, just ignore
             * any message types you're not interested in, or that you don't
             * recognize.
             */
            if (GoogleCloudMessaging.
                    MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
                //   sendNotification("Send error: " + extras.toString());
            } else if (GoogleCloudMessaging.
                    MESSAGE_TYPE_DELETED.equals(messageType)) {
                //      sendNotification("Deleted messages on server: " +
                //     extras.toString());
                // If it's a regular GCM message, do some work.
            } else if (GoogleCloudMessaging.
                    MESSAGE_TYPE_MESSAGE.equals(messageType)) {


                Log.i(TAG, "PUSHNOTIFICATION RECEIVED @ " + SystemClock.elapsedRealtime());


                extraData=extras.getString("extraData");
                from=extras.getString("from");
                title=extras.getString("title");
                message=extras.getString("message");

                Log.i(TAG, "Received: " + extras.toString()+" M"+messageType);




 if(title!=null) {
                    if(from.equals("google.com/iid"))
                    {
                        //related to google ... DO NOT PERFORM ANY ACTION
                    }
                    else { 
                      //HANDLE THE RECEIVED NOTIFICATION
                        }

答案 1 :(得分:3)

此处的根本问题是GCM API已更改。如OP所示,您可以简单地过滤掉这个新意图,但通过这样做您将错过令牌刷新通知

来自更新后的GCM sample code

的AndroidManifest.xml

<service
    android:name=".MyInstanceIdListenerService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.android.gms.iid.InstanceID"/>
    </intent-filter>
</service>

MyInstanceIdListenerService.java

public class MyInstanceIDListenerService extends InstanceIDListenerService {

    private static final String TAG = "MyInstanceIDLS";

    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. This call is initiated by the
     * InstanceID provider.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]
}

解决此问题的正确方法是更新新API的实施,详见更新后的GCM API docs

  

对于扩展WakefulBroadcastReceiver的现有应用程序,Google   建议迁移到GCMReceiver和GcmListenerService。至   迁移:

     

在应用清单中,将GcmBroadcastReceiver替换为   “com.google.android.gms.gcm.GcmReceiver”,并替换当前   将IntentService扩展到新的服务声明   GcmListenerService

     

从客户端代码中删除BroadcastReceiver实现

     

重构要使用的当前IntentService服务实现   GcmListenerService

     

有关详细信息,请参阅此页面中的示例清单和代码示例。

我发布了一个相关问题的答案,该问题提取了从旧实施here更新所需的所有相关代码。