2015-02-08 196 views
6

推後未收到此標記爲重複之前:應用程序被關閉

我讀過至少15個類似的線程,每一個或者是使用舊的解析代碼(現已棄用setDefaultPushCallback )或者問題是由於在一個活動中調用了Parse.initialize(...)而不是在Application類中。但這是而不是適用於我的情況。官方示例(我正在使用)顯然是正確的,所以代碼已經在Application類中。

我已經下載了Push Starter example from Parse's official guides,並在模擬器上試了一下。我只在應用程序運行時收到推送。一旦它關閉(從「最近的應用程序」列表中刪除,而不是強行殺死),我不再受到推動。這使得整個功能相當無用......我嘗試了使用和不使用GCM,其行爲是相同的。

任何線索什麼可能是錯誤的?所有類都是股票示例,我沒有任何重寫或添加(除了從指南中複製的id/key和ParsePush.subscribeInBackground調用)。奇怪的是,示例代碼不包含ParsePush.subscribeInBackground,並且QuickStart沒有提及它。它甚至給出了一個測試按鈕,據推測發送一個我從來沒有收到的推,有或沒有subscribeInBackground。到目前爲止,我已經能夠獲得推送的唯一方法是使用subscribeInBackground並通過Web控制檯手動發送推送,並且只有在應用程序正在運行時才這樣做。 Web控制檯也會告訴你有2個註冊的設備......這是不真實的。

清單:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.parse.starter" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="21"/> 

    <uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
    <uses-permission android:name="android.permission.WAKE_LOCK" /> 
    <uses-permission android:name="android.permission.VIBRATE" /> 
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 
    <uses-permission android:name="android.permission.GET_ACCOUNTS" /> 
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> 

    <!-- 
     IMPORTANT: Change "com.parse.starter.permission.C2D_MESSAGE" in the lines below 
     to match your app's package name + ".permission.C2D_MESSAGE". 
    --> 
    <permission android:protectionLevel="signature" 
     android:name="com.parse.starter.permission.C2D_MESSAGE" /> 
    <uses-permission android:name="com.parse.starter.permission.C2D_MESSAGE" /> 

    <application 
     android:name=".ParseApplication" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:allowBackup="true"> 
     <activity 
      android:name=".ParseStarterProjectActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

     <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.parse.ParsePushBroadcastReceiver" 
      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.parse.starter" /> 
      </intent-filter> 
     </receiver> 
    </application> 

</manifest> 

ParseApplication:

package com.parse.starter; 
... 

public class ParseApplication extends Application { 

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     // Initialize Crash Reporting. 
     ParseCrashReporting.enable(this); 

     // Enable Local Datastore. 
     Parse.enableLocalDatastore(this); 

     ParseUser.enableAutomaticUser(); 

     // Add your initialization code here 
     Parse.initialize(this, "***", "***"); 

     ParseACL defaultACL = new ParseACL(); 
     // Optionally enable public read access. 
     // defaultACL.setPublicReadAccess(true); 
     ParseACL.setDefaultACL(defaultACL, true); 

     ParsePush.subscribeInBackground("", new SaveCallback() { 
      @Override 
      public void done(ParseException e) { 
       if (e == null) { 
        Log.d("com.parse.push", "successfully subscribed to the broadcast channel."); 
       } else { 
        Log.e("com.parse.push", "failed to subscribe for push", e); 
       } 
      } 
     }); 
    } 
} 
+0

嗨Kaqqao,通過「解析方式」獲得推送通知將停止工作,只要你從最近的應用程序中終止你的應用程序。這是因爲殺死你的應用會破壞與Parse後端服務器的連接,因此服務器不能再推送任何東西。但是,通過GCM推送通知應該可以正常工作,即使您的應用程序被殺死(不會被強行停止)。這是因爲GCM通過Google Play服務工作,這是一款始終在後臺運行的應用程序,可以在需要時啓動應用程序(而不是強制停止)。你的代碼也看起來是正確的,所以我真的不明白這個問題。 – 2015-02-16 06:51:44

+0

我想知道是否存在包名稱衝突(因爲您使用與示例相同的包),這樣有多個應用程序具有相同的包,但具有不同的簽名。你可以嘗試將你的軟件包改成獨特的東西嗎? 'com.parse.kaqqao' – 2015-02-16 06:55:27

+0

@jmols OMG,看起來你的包名稱理論是正確的!在我更改名稱後,我開始接收關閉應用程序的消息。不知道爲什麼它可以與運行的應用程序一起工作,但是......無論如何,請您將您的兩條評論轉換爲答案,以便我可以在獎勵到期之前向您頒發獎金。 – kaqqao 2015-02-16 21:44:37

回答

1

只是爲了澄清爲什麼你看到這種行爲,解析在交付推送通知兩種不同的方式:

  1. 「Pa rse way「:Parse SDK有一個運行在你的應用程序中的組件,它保持與Parse後端服務器的連接。這隻會在您的應用程序實際運行時才起作用,因爲它會中斷與Parse後端的連接。
  2. GCM「Google」推送通知:此功能通過Google Play服務運行,該應用始終在後臺運行,並可在需要時啓動您的應用。這將始終有效,除非您強制停止應用程序。

就你而言,你存在包名衝突:com.parse.starter是實際包含在該示例中的包名。這會導致GCM無法工作,因爲它已經知道不同簽名下的包。將您的軟件包名稱更改爲像com.parse.kaqqao這樣的獨特軟件應該可以解決這個問題。

1

這有幾個原因:

  1. 有兩個廣播接收器即在 「com.parse.ParsePushBroadcastReceiver」 和 「com.parse.GcmBroadcastReceiver」。我相信第一個接收器優先於GCMBroadcastReceiver,因此這種行爲不會因移除或保留這個接收器而受到影響。這也可能是由於「com.parse.push.intent.RECEIVE」操作,這可能是處理推送消息RECEIVE操作。如果兩個接收器都執行解析Push消息的相同任務(在後臺啓動相同的服務),那麼將intent-filter包含在一個接收器中,讓它處理各種推送消息。由於GCMBroadcastReceiver擁有C2DM許可。

  2. 嘗試更改清單中兩個廣播接收器標記的順序。 (在ParsePushBroadcastReceiver之前保留GCMBroadcastReceiver)

  3. 可能是由於android:exported =「false」,也許它會阻止Receiver偵聽服務器發送的推送消息。嘗試更改爲true。