2014-05-22 41 views
7

這很簡單,當您在移動設備上首次使用解析時,它就像魅力一樣。 當您重新安裝應用程序時,它會擰緊所有內容。「至少要在此操作中指定一個ID字段(installationId,deviceToken)」解析

正如Eranstackoverflow說:

「PushService.subscribe似乎緩存認購本地存儲,以避免重新訂閱當你多次啓動應用程序 這是第一個參數。該方法用於: 背景 - 這是用來訪問本地存儲緩存認購,所以當前必須是一個可行的情況下 (引自here

然而,當y。如果您卸載該應用程序,該應用程序的本地存儲將從您的設備中刪除,因此新安裝將導致PushService.subscribe重新註冊到Google Cloud Messaging。如果新註冊返回一個新的註冊ID,則Parse將有兩個註冊ID,可用於將推送通知發送到您的應用程序,並且它們都將鏈接到您提供用於訂閱的相同userName。因此,向該用戶名發送通知會將其發送到兩個註冊ID,導致它到達兩次。

當解析發送給你的通知,他們應該從谷歌獲得與canonical_registration_id的響應,這將讓他們知道你的應用程序在設備上相關聯的註冊ID之一是老了,不應該再使用。因此(假設解析有一個體面的實施GCM)的下一次發送通知到您的設備的時候,你應該得到它只有一次「

下面是安裝我的源代碼。

String androidId = Secure.getString(getApplicationContext().getContentResolver(),Secure.ANDROID_ID); 
Parse.initialize(this, "KEY1", "KEY2"); 
PushService.setDefaultPushCallback(this, ParseActivity.class); 

ParseInstallation installation = ParseInstallation.getCurrentInstallation(); 
installation.put("UniqueId",androidId); 

installation.setObjectId(null); 

installation.saveInBackground(); 

我的堆棧跟蹤(如每個人):

05-20 19:47:35.630: E/ParseCommandCache(6497): com.parse.ParseException: at least one ID field (installationId,deviceToken) must be specified in this operation 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.ParseCommand.onPostExecute(ParseCommand.java:334) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.ParseRequest$5.then(ParseRequest.java:321) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.ParseRequest$5.then(ParseRequest.java:318) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11.run(Task.java:481) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$ImmediateExecutor.execute(Task.java:673) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.completeAfterTask(Task.java:477) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.continueWithTask(Task.java:353) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.continueWithTask(Task.java:364) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$9.then(Task.java:410) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$9.then(Task.java:402) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11.run(Task.java:481) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$ImmediateExecutor.execute(Task.java:673) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.completeAfterTask(Task.java:477) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.access$400(Task.java:22) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$7.then(Task.java:346) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$7.then(Task.java:343) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.runContinuations(Task.java:510) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.access$800(Task.java:22) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$TaskCompletionSource.trySetResult(Task.java:565) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$TaskCompletionSource.setResult(Task.java:599) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11$1.then(Task.java:493) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11$1.then(Task.java:485) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$10.run(Task.java:448) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$ImmediateExecutor.execute(Task.java:673) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.completeImmediately(Task.java:444) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.access$300(Task.java:22) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$6.then(Task.java:311) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$6.then(Task.java:308) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.runContinuations(Task.java:510) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.access$800(Task.java:22) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$TaskCompletionSource.trySetResult(Task.java:565) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$TaskCompletionSource.setResult(Task.java:599) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11$1.then(Task.java:493) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11$1.then(Task.java:485) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$10.run(Task.java:448) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$ImmediateExecutor.execute(Task.java:673) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.completeImmediately(Task.java:444) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.access$300(Task.java:22) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$6.then(Task.java:311) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$6.then(Task.java:308) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.runContinuations(Task.java:510) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.access$800(Task.java:22) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$TaskCompletionSource.trySetResult(Task.java:565) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$TaskCompletionSource.setResult(Task.java:599) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11$1.then(Task.java:493) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11$1.then(Task.java:485) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$10.run(Task.java:448) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$ImmediateExecutor.execute(Task.java:673) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.completeImmediately(Task.java:444) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.continueWith(Task.java:318) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.continueWith(Task.java:329) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11.run(Task.java:485) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$ImmediateExecutor.execute(Task.java:673) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.completeAfterTask(Task.java:477) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.access$400(Task.java:22) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$7.then(Task.java:346) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$7.then(Task.java:343) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.runContinuations(Task.java:510) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.access$800(Task.java:22) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$TaskCompletionSource.trySetResult(Task.java:565) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$TaskCompletionSource.setResult(Task.java:599) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11$1.then(Task.java:493) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11$1.then(Task.java:485) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$10.run(Task.java:448) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$ImmediateExecutor.execute(Task.java:673) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.completeImmediately(Task.java:444) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.continueWith(Task.java:318) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task.continueWith(Task.java:329) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at com.parse.Task$11.run(Task.java:485) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
05-20 19:47:35.630: E/ParseCommandCache(6497): at java.lang.Thread.run(Thread.java:841) 
05-20 19:48:32.615: D/Request(6497): Warning: Sessionless Request needs token but missing either application ID or client token. 

因爲我還沒有發現任何真正的解決辦法,我問這裏

謝謝

+0

您是否找到解決方案? –

+0

@Binghammer你有同樣的問題嗎?我仍然沒有解決方案...已經在'Parse'論壇上提出問題,並在Facebook Developers中放置了一個新Bug。 –

+1

是的,我有同樣的問題。檢查我的問題,也許它可以幫助你? http://stackoverflow.com/questions/23860586/facebook-parse-login-behaving-strange –

回答

0

我絕對相信,這是由解析錯誤引起的。我在Parse.com發現的很多未解決的錯誤報告都說了同樣的事情。 我目前正在使用Parse 1.5.1: 我所看到的是,如果沒有deviceToken推送不會被髮送,並且沒有uniqueId,我們會在上面得到運行時錯誤。 如果我在註冊後立即發送UniqueId,則不保存deviceToken的行。 對我來說,解決方案,在Nexus 5的Nexus 4和索尼XPERIAË測試: 在你的應用程序類的onCreate()

Parse.initialize(this, PARSE_APP_KEY_VALUE, PARSE_CLIENT_KEY_VALUE); 
    PushService.setDefaultPushCallback(getApplicationContext(), MainActivity.class); 
    final ParseInstallation installation = ParseInstallation.getCurrentInstallation(); 
    final String androidId = Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID); 
     // Post the uniqueId delayed 
     Handler handler = new Handler(); 
     handler.postDelayed(new Runnable() { 
           @Override 
           public void run() { 
            installation.put("UniqueId", androidId); 
            installation.saveInBackground(new SaveCallback() { 
             @Override 
             public void done(ParseException e) { 
              // Saved! 
             } 
            }); 
           } 
          }, 10000 
     ); 

以這種方式工作,我能救正確行(與UNIQUEID和deviceToken ),併發送推送通知!乾杯!

+0

謝謝!但我已經通過創建一個服務器並自己實現GCM和APN的服務器端來解決我的問題(Node.JS的NPM上有很好的庫)。不管怎麼說,還是要謝謝你! –

+0

不錯的解決方案!歡迎您;) – marino

0

我也遇到過這個問題。我通過調用下面的方法排序的解決了這個問題我活動的onCreate()

/** 
    * Initialize Push Messaging Service and subscribe to all-users channel 
    */ 
    private void initParsePushMessaging() { 
     ParseInstallation parseInstallation = ParseInstallation 
       .getCurrentInstallation(); 
     //You might skip this if 
     if (ParseUser.getCurrentUser() != null) { 
      parseInstallation.put("user", 
        ParseUser.getCurrentUser()); 
     } 
     if (parseInstallation.getObjectId() != null) 
      parseInstallation.saveInBackground(new SaveCallback() { 

       @Override 
       public void done(ParseException e) { 
        PushService.subscribe(getApplicationContext(),"channel_name", 
          MainHomeActivity.class); 
       } 
      }); 

    } 

即使它並沒有完全解決我的問題,但現在我的應用程序不會掛起並沒有更多的ANR的,由於這個解析執行。如果我重新安裝一個應用程序並運行它,那麼應用程序會創建一個新的安裝記錄並刪除最後一個。唯一的問題是,channel_name這次運行沒有訂閱但是在下次運行通道成功訂閱

+0

嗨謝拉茲,你可以添加更多:1)什麼是ANR? 2)這段代碼如何刪除以前的安裝記錄? –

+0

@GabbarSingh ANR是應用程序不響應對話框。如果您在UI線程上執行任何需要3秒以上的操作[阻止UI線程超過3秒],通常會發生這種情況。至於刪除以前的安裝記錄,Parse通過用新記錄覆蓋舊安裝記錄來自動執行該操作。 –

+0

謝謝,我從論壇上收集到,Parse能夠爲iPhone應用程序維護一個安裝記錄,但爲Android應用程序創建多個安裝記錄(例如,當用戶更新應用程序時,舊的安裝記錄仍然存在,並且爲更新後的版本應用程序)。發送推送通知時,如果您按每個安裝的應用收取郵件費用(並且其中一些安裝ID已過時),則會出現此問題。你能否確認你是否看到了這個問題。我正在評估Parse的限制,並檢查是否值得圍繞它們或自己編寫後端。謝謝 –

0

什麼對我來說擺脫這個異常是使用saveEventually()而不是saveInBackground()

在這裏,你有a link我對一個類似問題的答案。

我認爲saveEventually()是一個更好的選擇,因爲它確保安裝將始終保存,不管網絡可用性如何。相反,由於沒有網絡連接,saveInBackground()有可能導致保存失敗。此外,saveEventually()您不需要進行任何錯誤檢查,您應該在SaveCallback()saveInBackground()中執行錯誤檢查。

0

有完全相同的問題。我通過在手機上進行設置來解決它 - >應用程序 - >您的應用程序名稱 - >強制關機 - >卸載。

然後在Android工作室我去了 - >文件 - >無效緩存/重啓 - >等待gradle再次構建,然後在我的手機上運行應用程序。像魅力一樣工作。

相關問題