2010-04-11 85 views
9

我有一個Android應用程序需要在整個一天偶爾醒來。如何將數據從BroadcastReceiver傳遞到正在啓動的活動?

爲此,我使用AlarmManager設置PendingIntent並使此觸發器成爲BroadcastReceiver。這個BroadcastReceiver然後啓動一個活動將UI帶到前臺。

所有上述似乎工作,活動正確啓動;但我希望BroadcastReceiver通知Activity它是由鬧鐘啓動的(而不是由用戶啓動)。要做到這一點,我想,從廣播接收器的的onReceive()方法來設置一個變量的意圖的額外捆綁,即:

Intent i = new Intent(context, MyActivity.class); 
    i.putExtra(wakeupKey, true); 
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    context.startActivity(i); 

在的onResume()方法我的活動,我則尋找這個布爾變量的存在:

protected void onResume() { 
    super.onResume(); 

    String wakeupKey = "blah";  
    if (getIntent()!=null && getIntent().getExtras()!=null) 
     Log.d("app", "onResume at " + System.currentTimeMillis() + ":" + getIntent().getExtras().getBoolean(wakeupKey)); 
    else 
     Log.d("app", "onResume at " + System.currentTimeMillis() + ": null"); 
} 

中的onResume()始終返回null的getIntent()getExtras()調用 - 我似乎沒有能夠通過在所有傳遞任何額外的意味。束。

如果我使用相同的方法綁定extras到觸發BroadcastReceiver的PendingIntent,但是額外事情通過很好。

任何人都可以告訴我,從BroadcastReceiver傳遞一個包到一個Activity有什麼不同,而不是從一個Activity傳遞包到BroadcastReceiver?我擔心我可能會在這裏做出非常明顯的錯誤...

+0

奇妙而又奇妙...它剛開始工作(在模擬器),正是我所期待。重複了一下。我關閉了模擬器,重新啓動(沒有任何代碼更改或重新編譯),我又回到了舊的行爲(Activity啓動但沒有通過Bundle)。 我可以看到兩個運行的日誌仍然在前者中,Bundles正在通過,而後者沒有。 – 2010-04-11 11:46:45

回答

30

只是爲了說清楚(因爲我用了很多時間搞清楚如何使它工作)

在服務類擴展BroadcastReceiver。把下面的代碼在onReceive()

Intent intent2open = new Intent(context, YourActivity.class); 
intent2open.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
intent2open.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
String name = "KEY"; 
String value = "String you want to pass"; 
intent2open.putExtra(name, value); 
context.startActivity(intent2open); 

FLAG_ACTIVITY_SINGLE_TOP可以確保應用不會重新打開,如果已經打開。這意味着首先打開YourActivity的「舊」意圖會被重用,並且不會包含額外的值。你必須趕上他們叫onNewIntent()另一種方法在YourActivity.

public class YourActivity extends Activity { 
    private String memberFieldString; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     // Code doing your thing... 
    } // End of onCreate() 

    @Override 
    protected void onNewIntent(Intent intent) { 
    Log.d("YourActivity", "onNewIntent is called!"); 

    memberFieldString = intent.getStringExtra("KEY"); 

    super.onNewIntent(intent); 
} // End of onNewIntent(Intent intent) 

    @Override 
    protected void onResume() { 
     if (memberFieldString != null) { 
      if (opstartsIntent.getStringExtra(KEY) != null) { 
       Log.d("YourActivity", "memberFieldString: "+ memberFieldString); 
      } else { 
       Log.d("YourActivity", "The intent that started YourActivity did not have an extra string value"); 
      } 
     } 
    } // End of onResume() 

} // End of YourActivity 

請注意兩個if語句 - 在onResume()不知道以後OnCreate()->OnStart() OR onRestart()->onStart()
請參閱它被稱爲:http://www.anddev.org/images/android/activity_lifecycle.png

這只是用於測試該應用程序是否由用戶啓動(意圖沒有額外)或由BroadcastReceiver(意圖與額外)。

+0

但stl我面臨同樣的問題? ..我的活動開始一次又一次..有任何其他更新? – CoDe 2012-01-18 08:44:02

+1

這可能聽起來很愚蠢:但是你有沒有檢查過你是否設置了正確的標誌並按照描述對每個點進行了檢查?我花了很長時間才弄明白這一點,並且我意識到並非所有的標誌都像我期望的那樣工作。如果您添加比所描述的更多的標誌,請嘗試刪除它們。做好這項工作,然後逐個添加它們以查看會發生什麼。 – Norfeldt 2012-01-19 17:31:34

+1

什麼是「opstartsIntent」我無法找到/編譯它。 – MrHIDEn 2013-08-10 23:29:42

2

而不是getIntent().getExtras().getBoolean(wakeupKey)這是更傳統的寫getIntent().getBooleanExtra(wakeupKey, defaultValue)。我無法確定這是否與您的問題有關,但是在getExtras()內部創建一個我不確定的包,所以它可能值得一試。

+0

謝謝吉姆。試圖做出這種改變,但價值永遠是假的(我只是把它設置爲真)。 – 2010-04-11 11:48:50

5

該廣播接收器,然後啓動一個 活動帶來的UI到 前景。

這可能是你問題的關鍵。嘗試覆蓋onNewIntent(),看看傳遞給它的Intent是否有額外的。如果是這樣,那是因爲您在清單中設置了活動的方式(例如,您正在使用singleTop)以及在此特定情況下活動已存在的事實。

你也可以考慮擺脫i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);,看看這個變化是否重要。

結果是,你正在做的 - 把Intent的額外startActivity() - 應該工作得很好。實際上,您可以看到here的示例。這表明它對於活動(例如,singleTop)或您調用活動的方式(例如,FLAG_ACTIVITY_NEW_TASK)很有意思。

編輯:

自從我第一次出手沒工作,並給予你的「奇怪之處」上述評論...

這感覺有點像一個PendingIntent - 這些,除非你採取措施,您將無法更新附加內容。

想一想,請在清單中爲您的活動添加第二個<intent-filter>,只是在某個唯一的操作字符串上,然後嘗試從接收方開始使用該活動。或者,只需將接收器使用的startActivity()中的某個動作字符串扔進您的Intent中,而不會混淆清單。

+0

不,onNewIntent()不會得到它要麼... 的FLAG_ACTIVITY_NEW_TASK是存在的,因爲沒有它,我得到一個RuntimeException: E/AndroidRuntime(274):了java.lang.RuntimeException:無法啓動接收器融爲一體。 futureplatforms.twitchr.BirdArrivesAlarmReceiver:android.util.AndroidRuntimeException:從Activity上下文外部調用startActivity()需要FLAG_ACTIVITY_NEW_TASK標誌。這真的是你想要的嗎? – 2010-04-11 12:09:41

+0

我編輯了我以前的答案與其他的東西,你可以嘗試 - 評論在這裏,如果你沒有得到通知的答案編輯... – CommonsWare 2010-04-12 12:39:59

+1

好了,再試一次。 onNewIntent()現在可以實現 - 我將活動啓動模式更改爲singleTask,它的工作方式與我的希望完全相同。然後,我重寫newIntent並設置一個變量,這個變量可以在其他地方找到,以確定它已被警報喚醒。 謝謝! – 2010-04-18 17:13:41

1
SingleTop作品(不與其他標誌混用)

設置標誌

Intent intent = new Intent(ContextManager.getContext(),OrderList.class); 
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
Bundle bundle = new Bundle();  

bundle.putString("username",username); 
bundle.putString("password",password); 

intent.putExtras(bundle); 
startActivityForResult(intent,0); 
0

只是覆蓋onNewIntent這樣和捆綁VAR將在的onResume方法可用:

@Override 
protected void onNewIntent(Intent intent) { 
    super.onNewIntent(intent); 
    setIntent(intent); 
} 
相關問題