StartActivity () von außerhalb einer Aktivität aufrufen?

196

Ich verwende ein AlarmManager, um eine Absicht auszulösen, die ein Signal sendet. Folgendes ist mein Code:

AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(this, Wakeup.class);
try
{
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
    Long elapsed +=  // sleep time;
    mgr.set(AlarmManager.RTC_WAKEUP, elapsed, pi);
}
catch(Exception r)
{
    Log.v(TAG, "RunTimeException: " + r);
}

Ich rufe diesen Code von einem auf Activity, daher weiß ich nicht, wie ich den folgenden Fehler erhalten könnte ...

ERROR/AndroidRuntime(7557): java.lang.RuntimeException: Unable to start receiver com.wcc.Wakeup: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
Tom G.
quelle

Antworten:

494

Wenn Ihre Android-Version unter Android-6 liegt, müssen Sie diese Zeile hinzufügen, da sie sonst über Android-6 funktioniert.

...
Intent i = new Intent(this, Wakeup.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
Cristian
quelle
8
ja das funktioniert Wenn Sie jedoch mehrere Instanzen derselben Aktivität starten möchten, funktioniert dies nicht. Da die FLAG_ACTIVITY_NEW_TASK die gleiche bestehende Aktivität wieder aufnehmen wird
Ovidiu Latcu
7
Fügen Sie das Flag FLAG_ACTIVITY_Multiple_TASKS hinzu, um Ihr Problem zu lösen
Pavankumar Vijapur
Hüten Sie sich vor, Sie müssen diese auf Android 9+ auch, sehen Sie diese Antwort für Klärungen
Vadim Kotov
55

Verwenden Sie für mehrere Instanzen derselben Aktivität das folgende Snippet:

Hinweis : Dieses Snippet verwende ich außerhalb meines Activity. Stellen Sie sicher, dass Ihre AndroidManifestDatei nicht enthält android:launchMode="singleTop|singleInstance". Bei Bedarf können Sie es in ändern android:launchMode="standard".

Intent i = new Intent().setClass(mActivity.getApplication(), TestUserProfileScreenActivity.class);  
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);

// Launch the new activity and add the additional flags to the intent
mActivity.getApplication().startActivity(i);

Das funktioniert gut für mich. Hoffe, das spart jemandem Zeit. Wenn jemand einen besseren Weg findet, teilen Sie uns dies bitte mit.

Nandagopal T.
quelle
5
Bitte haben Sie Verständnis für den Unterschied zwischen den Methoden setFlags () und addFlag (). Jetzt starten Sie nur noch eine Aktivität mit FLAG_ACTIVITY_NEW_TASK. Wie im Code von Cristian unten.
JehandadK
-------------------------------------------------- ----------------- i.addFlag (Intent.FLAG_ACTIVITY_MULTIPLE_TASK); i.addFlag (Intent.FLAG_ACTIVITY_NEW_TASK); -------------------------------------------------- ----------------- i.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
JehandadK
42

Android Doc sagt -

Die Anforderung FLAG_ACTIVITY_NEW_TASK wird jetzt erzwungen

Mit Android 9 können Sie eine Aktivität nur in einem Nicht-Aktivitätskontext starten, wenn Sie das Absichtsflag FLAG_ACTIVITY_NEW_TASK übergeben haben. Wenn Sie versuchen, eine Aktivität zu starten, ohne dieses Flag zu übergeben, wird die Aktivität nicht gestartet und das System druckt eine Nachricht in das Protokoll.

Hinweis: Die Flag-Anforderung war immer das beabsichtigte Verhalten und wurde in Versionen unter Android 7.0 (API-Stufe 24) erzwungen. Ein Fehler in Android 7.0 verhinderte, dass die Flag-Anforderung durchgesetzt wurde.

Das bedeutet (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P), dass das Hinzufügen Intent.FLAG_ACTIVITY_NEW_TASKbeim Aufrufen startActivity()von außerhalb eines ActivityKontexts obligatorisch ist .

Es ist also besser, für alle Versionen ein Flag hinzuzufügen -

...
Intent i = new Intent(this, Wakeup.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
Hrishikesh Kadam
quelle
12

Sie haben den Teil, in dem Sie anrufen startActivity, nicht eingefügt , das ist der interessante Teil.

Möglicherweise rufen Sie startActivityin einem ServiceKontext oder in einem ApplicationKontext auf.

Drucken Sie "dies" aus, um die Katze zu protokollieren, bevor Sie den startActivityAnruf tätigen, und sehen Sie, worauf es sich bezieht. Manchmal wird versehentlich ein inneres "dies" verwendet.

Marmor
quelle
1
Dies ist wahrscheinlich das Problem, das OP hat. Ich bin dem gleichen begegnet. Das Starten einer Aktivität mit getApplicationContext () anstelle einer vorhandenen Aktivität löst diesen Fehler aus.
Hazen Hills Software
Schön :) Ich bin mir ziemlich sicher, dass dies der Fehler war, den ich den ganzen Abend zu entdecken versuche. Danke, Herr.
Martin Pfeffer
9

Manchmal kann dieser Fehler ohne expliziten Aufruf von auftreten startActivity(...). Einige von Ihnen haben beispielsweise in Crashlytics eine solche Stapelverfolgung gesehen:

Fatal Exception: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
       at android.app.ContextImpl.startActivity(ContextImpl.java:1597)
       at android.app.ContextImpl.startActivity(ContextImpl.java:1584)
       at android.content.ContextWrapper.startActivity(ContextWrapper.java:337)
       at android.text.style.URLSpan.onClick(URLSpan.java:62)
       at android.text.method.LinkMovementMethod.onTouchEvent(LinkMovementMethod.java:217)
       at android.widget.TextView.onTouchEvent(TextView.java:9522)
       at android.view.View.dispatchTouchEvent(View.java:8968)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.widget.AbsListView.dispatchTouchEvent(AbsListView.java:5303)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2559)
       at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1767)
       at android.app.Activity.dispatchTouchEvent(Activity.java:2866)
       at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:67)
       at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:67)
       at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2520)
       at android.view.View.dispatchPointerEvent(View.java:9173)
       at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4706)
       at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4544)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4121)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4087)
       at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4201)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4095)
       at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4258)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4121)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4087)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4095)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
       at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6564)
       at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6454)
       at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6425)
       at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6654)
       at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:143)
       at android.os.Looper.loop(Looper.java:130)
       at android.app.ActivityThread.main(ActivityThread.java:5942)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)

Und Sie fragen sich vielleicht, was Sie falsch gemacht haben, da der Trace nur Framework-Code enthält. Hier ist ein Beispiel, wie dies passieren kann. Nehmen wir an, wir sind in einem Fragment.

Activity activity = getActivity();
Context activityContext = activity;
Context appContext = activityContext.getApplicationContext();
LayoutInflater inflater = LayoutInflater.from(appContext); // whoops!
View view = inflater.inflate(R.layout.some_layout, parent, false);
TextView tvWithLinks = (TextView) view.findViewById(R.id.tv_with_links);

tvWithLinks.setMovementMethod(LinkMovementMethod.getInstance()); // whoops!!

Wenn ein Benutzer auf diese Textansicht klickt, stürzt Ihre App mit der obigen Stapelverfolgung ab. Dies liegt daran , das Layout inflater einen Verweis auf die hat Anwendungskontext , und so daher Ihre Textansicht hat einen Anwendungskontext. Durch Klicken auf diese Textansicht wird implizit aufgerufen appContext.startActivity(...).

Letzte Anmerkung: Ich habe dies auf Android 4, 5, 6 und 7 Geräten getestet. Es betrifft nur 4, 5 und 6. Android 7-Geräte haben anscheinend keine Probleme beim Anrufen appContext.startActivity(...).

Ich hoffe das hilft jemand anderem!

Autonome Apps
quelle
2

Dieselbe Fehler, mit der ich beim Erhalten einer Benachrichtigung auf den neuesten Android-Geräten 9 und 10 konfrontiert war.

Es hängt vom Startmodus ab, wie Sie damit umgehen. Verwenden Sie den folgenden Code: - android: launchMode = "singleTask"

Fügen Sie dieses Flag mit Intent hinzu: - intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);

Puneet Kumar
quelle
1

Versuchen Sie, in diese Zeile zu wechseln:

PendingIntent pendingIntent = PendingIntent.getBroadcast(getContext(), 0, i, 0);
Luís Ledebour
quelle
1

Ich möchte nur bemerken, dass startActivityeine Aktivität von außerhalb in einigen Android-Versionen (zwischen N und O-MR1) gültig ist und der interessante Punkt ist, dass es sich um einen Fehler im Android-Quellcode handelt!


Dies ist der Kommentar über der startActivityImplementierung. Siehe hier .

Das Aufrufen der Startaktivität von außerhalb einer Aktivität ohne FLAG_ACTIVITY_NEW_TASK ist im Allgemeinen nicht zulässig, es sei denn, der Anrufer gibt die Task-ID an, in der die Aktivität gestartet werden soll. Zwischen N und O-MR1 war ein Fehler vorhanden, der dies ermöglichte .

Fartab
quelle
Was ist die Lösung dafür
dominic_torreto
0

Wenn Sie eine Aktivität in Ihrer App öffnen möchten, können Sie die Methode startActivity () mit einem Intent als Parameter aufrufen. Diese Absicht wäre die Aktivität, die Sie öffnen möchten. Zuerst müssen Sie ein Objekt dieser Absicht erstellen, wobei der erste Parameter der Kontext und der zweite Parameter die Zielaktivitätsklasse ist.

Intent intent = new Intent(this, Activity_a.class);
startActivity(intent);

Hoffe das wird helfen.

Md. Shafiqur Rahman
quelle
3
Ich schreibe als Rezensent, weil Ihre Antwort als minderwertig gekennzeichnet wurde. Das Manko dieser Antwort ist, dass es keine Erklärung dafür gibt, was Ihr Code tut oder warum er das in der Frage aufgeworfene Problem löst. Würden Sie bitte einige erläuternde Kommentare hinzufügen, wobei zu berücksichtigen ist, dass viele Programmierer Ihre Antwort in Zukunft zur Orientierung lesen könnten. Danke dir!
Bill Bell
Wenn Sie eine Aktivität in Ihrer App öffnen möchten, können Sie die Methode startActivity () mit einem Intent als Parameter aufrufen. Diese Absicht wäre die Aktivität, die Sie öffnen möchten. Zuerst müssen Sie ein Objekt dieser Absicht erstellen, wobei der erste Parameter der Kontext und der zweite Parameter die Zielaktivitätsklasse ist. Hoffe das wird helfen.
Md. Shafiqur Rahman
OK. Aber anstatt diese Informationen in einen Kommentar einzufügen, sollten Sie Ihre Antwort bearbeiten und dort einfügen. Ich bedauere, diesen Punkt besprochen zu haben, aber es ist wichtig, dies für jede Antwort zu tun. Freundliche Grüße.
Bill Bell
Ja, bitte geben Sie an, warum Ihre Antwort richtig ist. Wir lernen nur, bessere Programmierer zu sein, wenn wir lernen, WARUM wir die Dinge tun, die wir tun.
Kiwicomb123