web-dev-qa-db-fra.com

Appel de startActivity () en dehors d'une activité?

J'utilise un AlarmManager pour déclencher une intention qui diffuse un signal. Voici mon 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);
}

J'appelle ce code depuis un Activity, donc je ne sais pas comment je pourrais avoir l'erreur suivante ...

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?
177
Tom G

si votre version de Android est inférieure à Android - 6, vous devez ajouter cette ligne, sinon elle fonctionnera au-dessus de Android - 6.

...
Intent i = new Intent(this, Wakeup.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
469
Cristian

Pour plusieurs instances de la même activité, utilisez l’extrait suivant,

Note: Cet extrait, j'utilise en dehors de mon Activity. Assurez-vous que votre fichier AndroidManifest ne contient pas Android:launchMode="singleTop|singleInstance". si nécessaire, vous pouvez le changer en 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);

Cela fonctionne bien pour moi. J'espère que cela fait gagner du temps à quelqu'un. Si quelqu'un trouve un meilleur moyen, veuillez partager avec nous.

51
Nandagopal T

Android Doc dit -

L'exigence FLAG_ACTIVITY_NEW_TASK est maintenant appliquée

Avec Android 9, vous ne pouvez pas démarrer une activité à partir d'un contexte de non-activité à moins de transmettre l'indicateur d'intention FLAG_ACTIVITY_NEW_TASK. Si vous essayez de démarrer une activité sans passer cet indicateur, l'activité ne démarre pas et le système imprime un message dans le journal.

Remarque: l'exigence d'indicateur a toujours été le comportement souhaité et a été appliquée aux versions inférieures à Android 7.0 (API de niveau 24). Un bogue dans Android 7.0 a empêché l'application de l'indicateur obligatoire.

Cela signifie que pour (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) il est obligatoire d’ajouter Intent.FLAG_ACTIVITY_NEW_TASK lors de l’appel de startActivity() de l’extérieur d’un contexte Activity.

Il est donc préférable d’ajouter un drapeau pour toutes les versions -

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

Vous n'avez pas collé la partie où vous appelez startActivity, c'est la partie intéressante.

Vous appelez peut-être startActivity dans un contexte Service ou dans un contexte Application.

Imprimez "ceci" pour enregistrer le chat avant de passer l'appel startActivity, et voyez à quoi il fait référence, il est parfois nécessaire d'utiliser un "ceci" interne par inadvertance.

12
marmor

Parfois, cette erreur peut se produire sans un appel explicite à startActivity(...). Par exemple, certains d'entre vous ont peut-être vu une trace de pile comme celle-ci dans Crashlytics:

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)

Et vous pouvez vous demander ce que vous avez fait de mal, car la trace n'inclut que du code framework. Eh bien, voici un exemple de la façon dont cela peut arriver. Disons que nous sommes dans un 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!!

Désormais, lorsqu'un utilisateur clique sur cette vue, votre application se bloque avec la trace de pile ci-dessus. Ceci est dû au fait que le inflater a une référence au contexte d'application, et que votre vue texte a donc un contexte d'application. En cliquant sur cette vue textuelle implicitement appelle appContext.startActivity(...).

Note finale: j'ai testé cela sur Android 4, 5, 6 et 7 appareils. Il concerne uniquement les appareils 4, 5 et 6. Android 7 n'a apparemment aucun problème à appeler appContext.startActivity(...).

J'espère que ça aidera quelqu'un d'autre!

9
AutonomousApps

Je veux juste noter que startActivity de l'extérieur d'une activité est valide dans certaines versions de Android (entre N et O-MR1) et le point intéressant est qu'il s'agit d'un bogue dans Android code source!


Ceci est le commentaire ci-dessus startActivity implémentation. Voir ici .

L'appel de l'activité de démarrage depuis l'extérieur d'une activité sans FLAG_ACTIVITY_NEW_TASK n'est généralement pas autorisé, sauf si l'appelant spécifie l'ID de la tâche dans laquelle l'activité doit être lancée. Un bogue existait entre N et O-MR1 qui l'autorisait. cela fonctionne .

1
Fartab

au lieu du contexte d'application (i.e .getApplication(); getApplicationContext();), vous devez utiliser le contexte d'activité dans ce cas ---> YourActivity.this

1

Essayez de passer à cette ligne:

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

Lorsque vous souhaitez ouvrir une activité dans votre application, vous pouvez appeler la méthode startActivity () avec un paramètre Intent. Cette intention serait l'activité que vous souhaitez ouvrir. Vous devez d'abord créer un objet de cette intention avec le premier paramètre comme contexte et le deuxième paramètre comme classe d'activité ciblée.

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

J'espère que cela aidera.

0