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以查看它是如何工作的。