web-dev-qa-db-fra.com

Appel de startActivity () en dehors d'un contexte d'activité

J'ai implémenté une ListView dans mon application Android. Je me lie à cette ListView en utilisant une sous-classe personnalisée de la classe ArrayAdapter. Dans la méthode ArrayAdapter.getView(...) remplacée, j'attribue une OnClickListener. Dans la méthode onClick de la OnClickListener, je souhaite lancer une nouvelle activité. Je reçois l'exception:

Calling startActivity() from outside of an Activity  context requires the  
FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

Comment puis-je obtenir la Context sous laquelle la ListView (la Activity actuelle) fonctionne?

292
Sako73

Non plus 

  • mettre en cache l'objet Context via le constructeur de votre adaptateur, ou
  • l'obtenir de votre vue.

Ou en dernier recours,

  • ajoutez le drapeau FLAG_ACTIVITY_NEW_TASK à votre intention:

_

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Modifier - J'éviterais de définir des indicateurs car cela interférerait avec le flux normal d'événements et la pile d'historique.

488
Alex Volovoy

Vous pouvez y parvenir avec - addFlags au lieu de setFlags

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Selon la documentation il fait:

Ajoutez des indicateurs supplémentaires à l'intention (ou avec la valeur des indicateurs existants).


MODIFIER

Sachez que si vous utilisez des indicateurs, vous modifiez la pile d'historique en La réponse d'Alex Volovoy dit:

... évitez de définir des indicateurs car cela interférerait avec le flux normal de la pile d'événements et d'historique.

84
Bruno Bieri

Au lieu d'utiliser (getApplicationContext), utilisez YourActivity.this

51
Jeffrey Nyauke

Si vous avez une erreur à cause de l'utilisation de create chooser comme ci-dessous:

Intent sharingIntent = new Intent(Intent.ACTION_VIEW);
sharingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sharingIntent.setData(Uri.parse("http://google.com"));
startActivity(Intent.createChooser(sharingIntent, "Open With"));

Définissez le drapeau pour créer un sélecteur comme ceci:

Intent sharingIntent = new Intent(Intent.ACTION_VIEW);
sharingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sharingIntent.setData(Uri.parse("http://google.com"));
Intent chooserIntent = Intent.createChooser(sharingIntent, "Open With");
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(chooserIntent);
24
sanath_p

Je pense que vous implémentez peut-être OnClickListener au mauvais endroit - en général, vous devez absolument implémenter un OnItemClickListener dans votre activité et le définir sur la liste à la place, sinon vous aurez des problèmes avec vos événements ...

13
mreichelt

De plus: si vous affichez des liens dans listview dans fragment , ne le créez pas comme ceci

    adapter = new ListAdapter(getActivity().getApplicationContext(),mStrings);

au lieu d'appeler

    adapter = new ListAdapter(getActivity(),mStrings);

adaptateur fonctionne bien dans les deux cas, mais les liens ne fonctionnent que dans le dernier.

10
djdance
CustomAdapter mAdapter = new CustomAdapter( getApplicationContext(), yourlist);

ou

Context mContext = getAppliactionContext();

CustomAdapter mAdapter = new CustomAdapter( mContext, yourlist);

changer en dessous

CustomAdapter mAdapter = new CustomAdapter( this, yourlist);
7
Murtaza Ashraf

Voir, si vous créez une intention dans un écouteur dans une méthode

override onClick (View v).

appelez ensuite le contexte à travers cette vue:

v.getContext ()

Il n'y aura même pas besoin de SetFlags ...

Cette erreur survient lorsque l’activité de démarrage ne sait pas quelle est son activité. Vous devez donc ajouter une activité avant startActivity ()

vous devez définir

activity.startActivity(yourIntent);
3
Cabezas

Pour tous ceux qui l'obtiennent sur Xamarin.Android (MonoDroid) même lorsque StartActivity est appelé à partir d'activité - il s'agit en fait d'un bogue Xamarin associé à la nouvelle exécution ART, voir https://bugzilla.xamarin.com/show_bug.cgi? id = 17630

3
rouen

À mon avis, il est préférable d'utiliser la méthode de startActivity() uniquement dans le code de votre Activity.class. Si vous utilisez cela dans la classe Adapter ou une autre classe, cela se traduira par cela.

2
kaosmys

J'ai eu le même problème. Le problème est avec le contexte. Si vous souhaitez ouvrir des liens (par exemple, partager un lien via le sélecteur), transmettez le contexte d'activité et non le contexte d'application.

N'oubliez pas d'ajouter myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) si vous n'êtes pas dans votre activité.

2
Coder29

Élaborer un peu plus la réponse d'Alex Volovoy -

si vous rencontrez ce problème avec des fragments, getActivity () fonctionne bien pour obtenir le contexte.

Dans d'autres cas:

Si vous ne voulez pas utiliser

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//not recommend

puis faites une fonction comme celle-ci dans votre OutsideClass -

public void gettingContext(Context context){
    real_context = context;//where real_context is a global variable of type Context
}

Désormais, dans votre activité principale, chaque fois que vous créez une nouvelle classe OutsideClass, appelez la méthode ci-dessus immédiatement après avoir défini la classe OutsideClass en donnant le contexte de l'activité en tant qu'argument .

public void startNewActivity(final String activity_to_start) {
    if(activity_to_start.equals("ACTIVITY_KEY"));
    //ACTIVITY_KEY-is a custom key,just to
    //differentiate different activities
    Intent i = new Intent(MainActivity.this, ActivityToStartName.class);
    activity_context.startActivity(i);      
}//you can make a if-else ladder or use switch-case

revenez maintenant à votre OutsideClass, et pour commencer une nouvelle activité, faites quelque chose comme ceci-

@Override
public void onClick(View v) {
........
case R.id.any_button:

            MainActivity mainAct = (MainActivity) real_context;             
            mainAct.startNewActivity("ACTIVITY_KEY");                   

        break;
    }
........
}

De cette façon, vous pourrez démarrer différentes activités appelées à partir de différentes OutsideClass sans vous embrouiller avec des drapeaux. 

Remarque: essayez de ne pas mettre en cache l'objet contextuel via le constructeur de fragment (avec adapter, fin). Un fragment doit avoir un constructeur vide, sinon l'application se bloque dans certains scénarios.

rappelez-vous d'appeler 

OutsideClass.gettingContext(Context context);

dans la fonction onResume () également.

2
Flying Monkey

J'ai aussi eu le même problème. Vérifiez tout le contexte que vous avez passé. Pour ' liens ' il faut contexte d'activité pas contexte d'application

C'est l'endroit où vous devriez vérifier: 

1.) Si vous avez utilisé LayoutInflater , vérifiez quel contexte vous avez passé.

2.) Si vous utilisez Adapter vérifiez quel contexte vous avez passé.

2
codemaniac
Intent viewIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);    
viewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    
startActivity(viewIntent);   

j'espère que cela fonctionnera.

1
Chirag Patel

Face au même problème puis mis en œuvre 
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
et a résolu le problème.

Il peut y avoir une autre raison liée à l'adaptateur d'affichage de liste.
Vous pouvez voir Ce blog , le décrit très bien.

1
Mayank Sharma

utilisez ce code. fonctionne bien pour moi; Partager quelque chose hors d'une activité

            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setType("text/plain");

            // Append Text
            String Text = "Your Text Here"

            intent.putExtra(Intent.EXTRA_TEXT, Text);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);


            Intent shareIntent = Intent.createChooser(intent,"Share . . . ");
            shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            G.context.getApplicationContext().startActivity(shareIntent);
1
Pooya Hayati

Au Android 28(Android P) startActivity

if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
        && (targetSdkVersion < Build.VERSION_CODES.N
                || targetSdkVersion >= Build.VERSION_CODES.P)
        && (options == null
                || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
    throw new AndroidRuntimeException(
            "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
}

Donc, le meilleur moyen est d'ajouter FLAG_ACTIVITY_NEW_TASK

Intent intent = new Intent(context, XXXActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
1
Alen Lee

Étant donné que l'ajout d'indicateurs affecte event_flow et stack_history, il est préférable de transmettre le "contexte d'application" à la non-activité à partir de laquelle vous devez appeler une classe d'activité de la manière suivante:

"ActivityClassName.this" (pendant que vous transmettez le contexte de cette manière, il contiendra tous les détails et toutes les informations nécessaires pour appeler une activité à partir d'un scénario de non-activité)

Il n'est donc pas nécessaire de définir ou d'ajouter des drapeaux, cela fonctionnera dans tous les cas.

0
Musthafa

Si vous appelez le partage d'intention dans le plug-in Cordova, la définition du drapeau ne vous aidera pas. Utilisez plutôt ceci - 

cordova.getActivity().startActivity(Intent.createChooser(shareIntent, "title"));
0
Sandeep Kumar

Utilisez ce code dans votre Adapter_Activity et utilisez context.startActivity(intent_Object) et intent_Object.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

Comme ça:

            Intent n_act = new Intent(context, N_Activity.class);
            n_act.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(n_act);

Ça marche....

0
Gaurav Lambole

Version Kotlin

val intent = Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
this.startActivity(intent)
0

Ma situation était un peu différente, je testais mon application avec Espresso et je devais lancer mon activité avec ActivityTestRule à partir de l'instrumentation Context (qui n'est pas celle qui provient d'un Activity).

    fun intent(context: Context) = Intent(context, HomeActivity::class.Java)
            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

Je devais changer les drapeaux et ajouter une or bitwise (| en Java) avec Intent.FLAG_ACTIVITY_NEW_TASK

Donc, il en résulte:

    fun intent(context: Context) = Intent(context, HomeActivity::class.Java)
            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
0
Rafael Ruiz Muñoz
Intent i= new Intent(context, NextActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
0
Chandan Lal