2013-05-01 76 views
3

我有一個使用Urban Airship用於推送通知的應用程序。當通知到達並且用戶點擊它時,應用程序中的活動A應該打開並執行一些操作。活動打開兩次

我已經安裝BroadcastReceiver如圖所示in the docs,它的幾乎工作。

  1. 當我的應用程序在前臺時,我不讓用戶看到通知,只是自動處理它。
  2. 當我的應用程序根本沒有運行時,活動開啓得很好。
  3. 當我的應用程序在背景中(其總是會發生當A是頂端活動),活動A的第二實例被創建

這是當然的,出了問題。我不想要兩個A活動,我只想要其中的一個。下面是相關的BroadcastReceiver代碼:

@Override 
public void onReceive(Context ctx, Intent intent) 
{ 
    Log.i(tag, "Push notification received: " + intent.toString()); 
    String action = intent.getAction(); 
    int notificationId = intent.getIntExtra(PushManager.EXTRA_NOTIFICATION_ID, -1); 
    if(action.equals(PushManager.ACTION_NOTIFICATION_OPENED)) 
    { 
     Intent intentActivity = new Intent(ctx, ActivityA.class); 
     intentActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     UAirship.shared().getApplicationContext().startActivity((intentActivity); 
    } 
} 

更新: 我試圖通過調用System.exit(0)當用戶按下後退上的活動A.過程結束繞過這個bug,但隨後立即重新啓動!我的廣播接收器不會再次被調用。發生了什麼?

更新2: @codeMagic詢問了有關應用程序和活動A.

這個程序可以讓其用戶檢討某些項目和評論對他們的更多信息。活動A在應用程序啓動時啓動。如果用戶的會話不再有效,則啓動登錄活動。用戶登錄後,活動A再次變爲活動狀態。 A只有一個「No items to review」消息和一個「立即嘗試」按鈕。

當用戶登錄時,服務器開始發送推送通知,每當有新產品供審查。當應用程序獲取通知時,活動A訪問服務器並獲取下一個項目以供查看。該項目顯示在活動B中。一旦將評論提交給服務器,活動B完成,活動A再次成爲最高活動。

當用戶正在審查的項目(因爲活動所取的話)的服務器知道,直到審查提交不發送推送通知 - 意思是通知不能來,如果用戶沒有登錄或者如果用戶正在查看活動B.

儘管我同意這裏存在細微的競爭條件,但它並不會導致我所看到的問題 - 在測試中,我100%肯定沒有競爭條件 - 推送通知僅在後發送活動A再次變爲活動狀態。

+0

是活動你的應用程序或第三方活動,如相機的一部分..? – 2013-05-01 21:57:08

+0

我自己的活動。 – zmbq 2013-05-01 21:57:32

+0

我可能是錯的,但從您所描述的內容來看,聽起來並不像「Activity A」必須是「Activity」,但可能是「Service」或「BroadcastReceiver」。如果它只是監視更新並通知'活動B'或如果沒有項目顯示消息,則可以顯示'活動B'的消息 – codeMagic 2013-05-02 12:40:03

回答

12

的解決方案是一個launchMode='singleTask'添加到活動AndroidManifest.xml。結果,調用了相同活動實例的onNewIntent而不是新的活動。

+0

中澄清這麼好的答案。精湛的作品。只是想知道哪個方法在片段內調用此 – VVB 2015-11-27 09:54:35

+0

什麼是onNewIntent – 2015-12-10 13:35:55

+0

爲了澄清,您的意思是singleTask *啓動*活動,而不是*啓動*活動?兩者都不適合我。 – quantumpotato 2016-10-28 23:19:34

3

您可以使用多種Intent Flags之一。 FLAG_ACTIVITY_REORDER_TO_FRONT就是其中之一。這會將Activity置於堆棧的前面(如果它已經在堆棧中),如果沒有,則會創建一個新的實例。我相信你仍然需要FLAG_ACTIVITY_NEW_TASK如果你不是從Activity

Intent.FLAG_ACTIVITY_CLEAR_TOP也應該工作。但是這會清除堆棧上的其他Activities。這取決於你需要的其他功能。去翻Intent Flags,看看哪種方式最適合你

+0

不,它不起作用。我的活動創建了兩次(onCreate被調用兩次,中間沒有onDestroy)。 – zmbq 2013-05-01 22:28:52

+0

你在做什麼'活動A'?當「Activity」位於堆棧的頂部時,爲什麼您的應用總是處於後臺?你有什麼事情我們不知道,因爲那些'Flags'將不會創建一個新的實例 – codeMagic 2013-05-01 22:32:39

+0

我會在問題 – zmbq 2013-05-02 05:57:27

-1

好了,兩個音符在此:

  • 您可以通過艙單所以它是獨立於任何部分註冊的廣播接收器的應用程序。並使用單例模式(在應用程序某處保留對您活動的靜態引用),這樣您可以檢查它們是否爲活動查看並進行相應處理。

    // your activity A 
    
    @Override 
    public void onCreate(Bundle bundle) { 
        super.onCreate(bundle); 
        myActivityReference = this; 
    } 
    
    public void onPause() { 
        super.onPause(); 
        if (isFinishing()) { 
         myActivityReference = null; 
        } 
    } 
    
  • ,或者你可以把一切都因爲它是和使用活動共進午餐模式的標誌在您的清單,如singleTop, singleInstance ... etc。看看這裏android activity lunch modes