2010-04-11 8 views
9

Mam aplikację na Androida, która musi być budzona sporadycznie przez cały dzień.Jak przekazać dane z BroadcastReceiver do uruchamianego działania?

Aby to zrobić, używam programu AlarmManager, aby skonfigurować moduł PendingIntent i ustawić ten wyzwalacz na BroadcastReceiver. To BroadcastReceiver następnie rozpoczyna działanie, aby przenieść interfejs na pierwszy plan.

Wszystko powyższe wydaje się działać, ponieważ Aktywność uruchamia się poprawnie; ale chciałbym, aby BroadcastReceiver powiadomił Aktywność, że został uruchomiony przez alarm (w przeciwieństwie do uruchamiania przez użytkownika). Aby to próbuję, czy z metody onReceive() z BroadcastReceiver ustawić zmienną w wiązce dodatkami z zamiarem, a więc:

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

W onResume() metodę mojej działalności, to wówczas spojrzeć na istnienie tej zmiennej logicznej:

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"); 
} 

getIntent() getExtras() wywołanie w onResume() zawsze zwraca null - I nie wydają się być w stanie przekazać żadnych dodatków, przez co wszystko w tym. pakiet.

Jeśli korzystam z tej samej metody, aby powiązać dodatki do PendingIntent, które wyzwala BroadcastReceiver jednak, dodatki są dobrze.

Czy ktoś może mi powiedzieć, co jest innego w przekazywaniu pakietu z BroadcastReceiver do działania, w przeciwieństwie do przekazywania pakietu z działania do BroadcastReceiver? Obawiam się, że mogę zrobić coś bardzo bardzo nie tak tutaj ...

+0

Curiouser i Curiouser ... to właśnie rozpoczął pracę (w emulatorze), dokładnie tak, jak ja się spodziewać . Trochę pracował przez chwilę. Wyłączyłem emulator, zrestartowałem (bez zmian kodu lub rekompilacji) i powróciłem do starego zachowania (Aktywność uruchamia się, ale pakiet nie przeszedł). Widzę dzienniki dla obu przebiegów - w pierwszym, Pakiety przechodzą, w drugim nie. –

Odpowiedz

30

Wystarczy, aby było jasne (bo kiedyś dużo czasu na zastanawianie się, jak sprawić, by to działało)

W klasa usług, która rozszerza BroadcastReceiver. Wstaw następujący kod w 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 pilnuje aplikacje nie ponownie otwarte, jeśli już otwarty. Oznacza to, że "stary" zamiar, który otworzył YourActivity w pierwszej kolejności, jest ponownie użyty i NIE zawiera dodatkowych wartości. Trzeba złapać je w innej metody zwanej onNewIntent() w 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 

Proszę zwrócić uwagę na dwa if - The onResume() nie wiem, czy to się nazywa po OnCreate()->OnStart() OR onRestart()->onStart()
proszę zobaczyć:http://www.anddev.org/images/android/activity_lifecycle.png

To właśnie służy do testowania, czy aplikacja została uruchomiona przez użytkownika (bez żadnych dodatków) LUB przez BroadcastReceiver (zamiar z dodatkami).

+0

ale stl mam ten sam problem? ..my aktywność zaczyna się od nowa. Czy masz jakieś inne aktualizacje? – CoDe

+1

To może zabrzmieć głupio: Ale czy sprawdziłeś, czy ustawiłeś odpowiednią flagę i podążałeś za opisem do każdego punktu?Dużo czasu zajęło mi zrozumienie tego i zdałem sobie sprawę, że nie wszystkie flagi działają tak, jak bym tego oczekiwał. Jeśli dodasz więcej flag niż opisanych, spróbuj je usunąć. Wykonaj tę pracę, a następnie dodaj je po kolei, aby zobaczyć, co się stanie. – Norfeldt

+1

Co to jest "opstartsIntent" Nie mogę znaleźć/skompilować tego. – MrHIDEn

2

Zamiast getIntent().getExtras().getBoolean(wakeupKey) jest bardziej konwencjonalne pisanie getIntent().getBooleanExtra(wakeupKey, defaultValue). Nie jestem pewien, czy jest to związane z twoim problemem, ale jest kilka rzeczy do zrobienia z tworzeniem pakietu wewnątrz getExtras(), którego nie jestem pewien, więc może i tak warto iść.

+0

Dzięki Jim. Po prostu próbowałem dokonać tej zmiany, ale wartość jest zawsze fałszywa (i ja tylko ustawiam ją na true). –

5

Ten BroadcastReceiver następnie uruchamia Aktywny przynieść UI do planie.

To może być sedno problemu tutaj. Spróbuj przesłonić numer onNewIntent() i sprawdzić, czy przekazana do niego Intent ma dodatkową wartość. Jeśli tak, to ze względu na sposób skonfigurowania działania w manifeście (np. Używasz singleTop) oraz fakt, że w tym konkretnym przypadku działanie już istniało.

Możesz także rozważyć pozbycie się i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i sprawdzić, czy to się zmieni.

Efekt jest taki, że to, co robisz - umieszczanie dodatkowego w Intent dla startActivity() - powinno działać dobrze. W rzeczywistości można zobaczyć przykłady tego here. Sugeruje to, że jest to coś ciekawego w działaniu (np. singleTop) lub sposób, w jaki wywołujesz aktywność (np. FLAG_ACTIVITY_NEW_TASK).

EDIT:

Ponieważ moje pierwsze strzały nie działa, i biorąc pod uwagę swoją „Curiouser” komentarz powyżej ...

to czuje się trochę jak PendingIntent - z tymi, chyba że podjąć kroki, nie będzie można aktualizować dodatków.

Z czystej kaprysu, spróbuj dodać drugą <intent-filter> do swojej aktywności w manifeście, po prostu na unikatowy ciąg akcji i spróbuj rozpocząć swoją działalność od swojego odbiorcy. Lub po prostu wrzuć łańcuch akcji do swojego Intent, który odbiornik używa do startActivity(), bez naruszania manifestu.

+0

Nie, onNewIntent() nie rozumiem albo ... FLAG_ACTIVITY_NEW_TASK jest tam, bo bez niego dostaję RuntimeException: E/Android Runtime (274): java.lang.RuntimeException: Nie można uruchomić odbiornik com. futureplatforms.twitchr.BirdArrivesAlarmReceiver: android.util.AndroidRuntimeException: Wywołanie funkcji startActivity() z poziomu kontekstu działania wymaga flagi FLAG_ACTIVITY_NEW_TASK. Czy to naprawdę jest to, czego chcesz? –

+0

Edytowałem moją wcześniejszą odpowiedź na inne rzeczy, które możesz wypróbować - komentując tutaj, jeśli nie otrzymasz powiadomienia o edycji odpowiedzi ... – CommonsWare

+1

OK, ponowienie ponownie. onNewIntent() robi to teraz - zmieniłem tryb uruchamiania działania na singleTask i działa dokładnie tak, jak się spodziewałem. Przeanalizowałem newIntent i ustawiłem zmienną, którą aktywność mogłaby wykryć w innym miejscu, aby stwierdzić, że została ona obudzona przez alarm. Dziękuję! –

1

Zestaw flag SingleTop działa (nie mieszać z innymi flagami)

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

Wystarczy zastąpić onNewIntent tak i var Bundle będą dostępne w onresume metody:

@Override 
protected void onNewIntent(Intent intent) { 
    super.onNewIntent(intent); 
    setIntent(intent); 
} 
Powiązane problemy