2

我正在使用解析在Android上发送目标推送通知。几次(不眠之夜包括)跟着教程,它完美的作品,但是在某些不可预知的事件,应用程序的Android用户停止接收通知。在Google Play上更新数小时后,肯定会发生这种情况。使用解析的Android推送在一段时间后停止工作

为了在不上载到Google Play的情况下进行复制,我缩小了范围,直到从清单更新应用程序的版本号并重新运行而不删除并重新安装。但是,在清单中进行简单的更改会使其再次起作用。然而,该解决方案并不可靠,因为它会在上传到生产后几小时/之后再次停止工作。

我正在使用自定义的ParsePushBroadcastReceiver播放自定义声音。我正在使用Google Play Services 5进行位置更新。我正在订阅我在以后的活动中推广的频道。有什么想法可能会导致这样的问题?下面的代码粘贴:

清单

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.xxx.xxx" 
    android:versionCode="19" 
    android:versionName="3.077" > 

    <uses-feature 
     android:glEsVersion="0x00020000" 
     android:required="true"/> 
    <!-- GCM PERMISSIONS --> 
    <permission android:name="com.xxx.xxx.permission.C2D_MESSAGE" android:protectionLevel="signature" /> 
    <uses-permission android:name="com.xxx.xxx.permission.C2D_MESSAGE" /> 
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> 
    <uses-permission android:name="android.permission.GET_ACCOUNTS" /> 
    <uses-permission android:name="android.permission.WAKE_LOCK" /> 
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 
    <uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
    <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
    <uses-permission android:name="android.permission.CALL_PHONE" /> 
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 
    <uses-permission android:name="android.permission.GET_ACCOUNTS" /> 
    <uses-permission android:name="android.permission.VIBRATE" /> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> 
    <uses-permission android:name="com.xxx.xxx.permission.MAPS_RECEIVE" /> 
    <application 
     android:name="com.xxx.xxx.MyApplication" 
     android:allowBackup="true" 
     android:allowClearUserData="true" 
     android:enabled="true" 
     android:icon="@drawable/icon" 
     android:logo= "@drawable/icon" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <uses-library android:name="com.google.android.maps" /> 

     <service android:name="com.xxx.xxx.xxxLocationService" /> 

     <meta-data 
      android:name="com.google.android.maps.v2.API_KEY" 
      android:value="xxxxxxxxxxx"/> 
     <meta-data android:name="com.google.android.gms.version" 
      android:value="@integer/google_play_services_version" /> 
     <meta-data android:name="com.parse.push.gcm_sender_id" 
        android:value="id:xxxxx" /> 
     <service android:name="com.parse.PushService" /> 
     <receiver android:name="com.parse.ParseBroadcastReceiver"> 
      <intent-filter> 
       <action android:name="android.intent.action.BOOT_COMPLETED" /> 
       <action android:name="android.intent.action.USER_PRESENT" /> 
      </intent-filter> 
     </receiver> 
     <receiver android:name="com.xxx.xxx.xxxBroadcastReceiver" 
      android:exported="false"> 
      <intent-filter> 
       <action android:name="com.parse.push.intent.RECEIVE" /> 
       <action android:name="com.parse.push.intent.DELETE" /> 
       <action android:name="com.parse.push.intent.OPEN" /> 
      </intent-filter> 
     </receiver> 
     <receiver android:name="com.parse.GcmBroadcastReceiver" 
      android:permission="com.google.android.c2dm.permission.SEND"> 
      <intent-filter> 
       <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
       <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 

       <!-- 
        IMPORTANT: Change "com.parse.starter" to match your app's package name. 
       --> 
       <category android:name="com.xxx.xxx" /> 
      </intent-filter> 
     </receiver> 
    </application> 

</manifest> 

应用类

public class MyApplication extends Application { 
     @Override 
     public void onCreate(){ 
      Parse.initialize(this, "xxxxxx", "xxxxxx"); 
      ParseInstallation.getCurrentInstallation().saveInBackground(); 
     } 
} 

依赖

dependencies { 
    compile 'com.google.android.gms:play-services:5.+' 
    compile 'com.google.code.gson:gson:2.3' 
    compile 'com.actionbarsherlock:actionbarsherlock:[email protected]' 
    compile 'com.android.support:support-v4:22.0.0' 
    compile files('libs/PayPal_MPL.jar') 
    compile files('libs/libGoogleAnalyticsServices.jar') 
    compile 'com.parse.bolts:bolts-android:1.1.4' 
    compile fileTree(dir: 'libs', include: 'Parse-*.jar') 
    compile files('libs/Parse-1.8.3.jar') 
} 

ParsePushBroadcastReceiver

public class xxxBroadcastReceiver extends ParsePushBroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     try { 
      String jsonData = intent.getExtras().getString("com.parse.Data"); 
      JSONObject json = new JSONObject(jsonData); 

      String title = null; 
      if(json.has("title")) { 
       title = json.getString("title"); 
      } 

      String message = null; 
      if(json.has("alert")) { 
       message = json.getString("alert"); 
      } 

      if(message != null) { 
       generateNotification(context, title, message); 
      } 
     } catch(Exception e) { 
      Log.e("NOTIF ERROR", e.toString()); 
     } 
    } 


    private void generateNotification(Context context, String title, String message) { 
     Intent intent = new Intent(context, MainActivity.class); 
     PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0); 

     NotificationManager mNotifM = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 

     if(title == null) { 
      title = context.getResources().getString(R.string.app_name); 
     } 

     final NotificationCompat.Builder mBuilder = 
       new NotificationCompat.Builder(context) 
         .setSmallIcon(R.drawable.icon) 
         .setContentTitle(title) 
         .setContentText(message) 
         .setStyle(new NotificationCompat.BigTextStyle() 
           .bigText(message)) 
         .addAction(0, "View", contentIntent) 
         .setAutoCancel(true) 
         .setDefaults(new NotificationCompat().DEFAULT_VIBRATE) 
         .setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.whistle)); 

     mBuilder.setContentIntent(contentIntent); 

     mNotifM.notify(randInt(100000000, 999999999), mBuilder.build()); 
    } 

    public static int randInt(int min, int max) { 

     // NOTE: Usually this should be a field rather than a method 
     // variable so that it is not re-seeded every call. 
     Random rand = new Random(); 

     // nextInt is normally exclusive of the top value, 
     // so add 1 to make it inclusive 
     int randomNum = rand.nextInt((max - min) + 1) + min; 

     return randomNum; 
    } 

} 

订阅频道

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_jobs); 

    ... 

    ParsePush.subscribeInBackground("driver"); 
} 

UPDATE

这里是我如何的时刻再现问题。我运行在调试模式下,它工作,然后我更改应用程序的版本号,并导出签名的应用程序进行生产(无需运行)。我将该已签名的APK安装到设备上(删除后)并且通知停止工作。似乎重写ParsePushBroadcastReceiver与它无关。如果我删除并以相同版本号的调试模式重新运行,直到我更改清单中的某些内容(如BroadcastReceiver)后才会起作用。这是我设法重现它的方式,但通知到达Google Play时(无论如何都会停止工作)(现在再试一次)。我错过了什么?

+0

您是否尝试在Parse仪表板上的应用程序设置中将生产中的Released开关切换为ON? – Slartibartfast 2015-03-25 05:36:53

+0

是的,它已开启。可能是因为某些原因,Google可能会阻止来自GCM的应用程序?我没有想法。 – ChrisBorg 2015-03-25 09:09:45

+0

版本号更改后,您的'onReceive'永远不会被调用?另外,你可以分享的任何日志?在纯粹的GCM实现中(意思是没有Parse),如果有问题,响应错误会被发送回你的应用服务器。 – Koh 2015-03-26 17:38:32

回答

4

example implementation是这样的评论:

// Check if app was updated; if so, it must clear the registration ID 
// since the existing registration ID is not guaranteed to work with 
// the new app version. 

我敢肯定,你遇到了这一点。因此解决方案是在更新后注册您的应用程序。我想在你的情况下,最好的选择是看看PACKAGE_REPLACED事件,在那里你应该再次注册你的应用程序。请检查this question以查看它是如何工作的。