Llamar a startActivity () desde fuera de un contexto de actividad

368

He implementado un ListViewen mi aplicación de Android. Me ato a esto ListViewusando una subclase personalizada de la ArrayAdapterclase. Dentro del ArrayAdapter.getView(...)método anulado , asigno un OnClickListener. En el onClickmétodo de la OnClickListener, quiero lanzar una nueva actividad. Me sale la excepción:

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

¿Cómo puedo obtener el Contextque el ListView(el actual Activity) está trabajando?

Sako73
fuente
1
Creo que la respuesta de Alex debería ser la solución 'aceptada' a su problema, ya que rectifica el error que mencionó de una manera más genérica
devanshu_kaushik
10
Me encanta que "¿Es esto realmente lo que quieres?" ... He recibido un mensaje antes que decía "¿Está seguro de que no olvidó anular el registro de un receptor de transmisión en alguna parte?" ¡INCREÍBLE! Felicitaciones a quien puso todos estos pequeños mensajes para ayudarnos a discutir.
Nerdy Bunz
1
Me encontré con este problema. cuando actualicé targetSdkVersion a 28.
illusionJJ

Respuestas:

575

Ya sea

  • almacenar en caché el objeto Context a través del constructor en su adaptador, o
  • obténgalo de su vista.

O como último recurso,

  • agregue el indicador FLAG_ACTIVITY_NEW_TASK a su intención:

_ _

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Editar: evitaría establecer marcas, ya que interferirá con el flujo normal de eventos y la pila de historial.

Alex Volovoy
fuente
66
¿Qué pasa con la función de enlace automático de TextView donde no puedo controlar la intención (y, por lo tanto, las marcas) creadas por el sistema?
Alex Semeniuk
75
Que estaba recibiendo esta excepción cuando estaba haciendo algo como esto context.startActivity(intent);acabo de cambiar contexta partir ApplicationContextde ActivityTipo. Esto solucionó el problema.
Sufian
@AlexSemeniuk ¿alguna vez encontraste una solución?
@AlexSemeniuk - AutoLink funcionará siempre que pase la actividad como contexto al adaptador
Georges
Pasé el objeto Context a través del constructor pero no funciona. pero FLAG_ACTIVITY_NEW_TASK funciona muy bien para mí, gracias.
Hiren
100

Puede lograrlo con addFlags en lugar desetFlags

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

De acuerdo con la documentación que hace:

Agregue banderas adicionales a la intención (o con el valor de banderas existente).


EDITAR

Tenga en cuenta que si está usando indicadores, cambia la pila del historial como dice la respuesta de Alex Volovoy :

... evite establecer marcas, ya que interferirá con el flujo normal de eventos y la pila de historial.

Bruno Bieri
fuente
1
Tengo un problema muy similar. ¿Ha experimentado algún problema con la pila de historial o cualquier otra cosa como sugieren las respuestas anteriores?
Einar Sundgren
1
No estoy exactamente seguro de lo que está buscando, pero puede comenzar una actividad sin un historial como ese: Intención intención = nueva intención (Intent.ACTION_VIEW, "http: \\ www.google.com")); intención. addFlags (Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity (intento);
Bruno Bieri
¿Por qué no se recomienda agregar banderas aquí? ¿Qué tan crítico es interferir con el flujo normal de eventos y la pila de historial?
Jason Krs
@JasonKrs puedes usar addFlags. Solo tenga en cuenta que puede cambiar la pila del historial dependiendo de la bandera que agregue. FLAG_ACTIVITY_NEW_TASK se puede usar en esta situación. Para obtener más detalles, lea: developer.android.com/reference/android/content/…
Bruno Bieri
64

En lugar de usar el (getApplicationContext)usoYourActivity.this

Jeffrey Nyauke
fuente
Esto funcionó para mí, es decir, usar en activity.startActivitylugar decontext.startActivity
Phani Rithvij
¡LA MEJOR RESPUESTA!
amirhossein
Esto funciona para mi.
user5722540
40

Si recibió un error debido al uso de crear selector como a continuación:

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

Establezca la bandera para crear un selector como este:

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);
sanath_p
fuente
44
Fue muy útil. ¡La intención exactamente de elección debería tener esta bandera!
Mahdi
2
Esta es la solución correcta, y exactamente lo que tiene que hacer, new_task in intent.chooser
Rafael Guimarães
15

Además: si muestra enlaces en la vista de lista en fragmentos , no lo cree así

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

en cambio llame

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

el adaptador funciona bien en ambos casos, pero los enlaces solo funcionan en el último.

djdance
fuente
@ user2676468: esto resolvió el problema del enlace automático para mí.
Head Geek
Esta debería ser una respuesta aceptada, ¡en lugar de usar banderas, es mejor!
Gastón Saillén
@ GastónSaillén, no uso getApplicationContext()(excepto la inicialización de la aplicación), pero capté esta excepción. Entonces, las situaciones pueden ser diferentes.
CoolMind
Este fue mi problema, usé getApplicationContext () para el contexto. Establecer thiscomo contexto funciona en relación con la actividad actual.
Brlja
14

Creo que tal vez está implementando OnClickListener en el lugar incorrecto; por lo general, definitivamente debe implementar un OnItemClickListener en su Actividad y configurarlo en ListView, o tendrá problemas con sus eventos ...

mreichelt
fuente
2
Me llevas a la solución. Necesitaba usar un OnItemClickListener, asignado a ListView. Aquí hay algunos enlaces para cualquier otra persona: developer.android.com/reference/android/widget/… androidpeople.com/… Gracias por la ayuda.
Sako73
Proporcione respuestas genéricas. La respuesta de Alex Volovoy a continuación resuelve el problema de manera genérica.
devanshu_kaushik
Para la posteridad: si lo define directamente como setListener (nuevo Listener) en un componente requiere un Contexto, creará una referencia implícita a toda la actividad que perderá memoria como no creería. Esto se puede eludir haciendo un oyente de clase interna estático o moviendo el oyente a una clase separada si necesita poder manejar entradas de más de un origen.
G_V
9
CustomAdapter mAdapter = new CustomAdapter( getApplicationContext(), yourlist);

o

Context mContext = getAppliactionContext();
CustomAdapter mAdapter = new CustomAdapter( mContext, yourlist);

cambiar a continuación

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

Al Android 28(Android P)principio Actividad

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

Entonces la mejor manera es agregar 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);
Alen Lee
fuente
Esto es necesario para dispositivos de 28 y superiores.
Md Mohsin el
7

Mira, si estás creando una intención dentro de un listado en algún método

override onClick (View v).

luego llame al contexto a través de esta vista también:

v.getContext ()

Ni siquiera necesitará SetFlags ...

Paulo Linhares - Packapps
fuente
¿Y cuál era la situación incorrecta? v.getApplicationContext ()?
CoolMind
3

Para cualquiera que tenga esto en Xamarin.Android (MonoDroid) incluso cuando se llama a StartActivity desde la actividad, esto es realmente un error de Xamarin con el nuevo tiempo de ejecución ART, consulte https://bugzilla.xamarin.com/show_bug.cgi?id=17630

Ruán
fuente
Sí, solo tiene que hacer lo que se describió anteriormente, pero la redacción ha cambiado ... intent.SetFlags (ActivityFlags.NewTask);
Luke Alderton el
3

Elaborando la respuesta de Alex Volovoy un poco más:

en caso de que tenga este problema con fragmentos, getActivity () funciona bien para obtener el contexto

En otros casos:

Si no quieres usar

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

luego realice una función como esta en su OutsideClass -

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

Ahora, en su actividad principal, cuando realice una nueva clase OutsideClass, llame al método anterior inmediatamente después de definir la clase OutsideClass dando el contexto de la actividad como argumento. También en su actividad principal haga una función

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

ahora regrese a su clase externa y, para comenzar una nueva actividad, haga algo como esto:

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

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

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

De esta manera, podrá iniciar diferentes actividades llamadas desde diferentes OutsideClass sin meterse con banderas.

Nota: intente no almacenar en caché el objeto de contexto a través del constructor para el fragmento (con adaptador, está bien). Un fragmento debe tener un constructor vacío; de lo contrario, la aplicación se bloquea en algunos escenarios.

recuerda llamar

OutsideClass.gettingContext(Context context);

en la función onResume () también.

Mono volador
fuente
3

Este error ocurre cuando startactivity no sabe cuál es su actividad. Por lo tanto, debe agregar actividad antes de startActivity ()

debes establecer

context.startActivity(yourIntent);
Cabezas
fuente
Si llama startActivitydesde Fragment, una persona que llama a menudo puede ser un fragmento, no una actividad.
CoolMind
2

En mi opinión, es mejor usar el método startActivity()solo en el código de su Activity.class. Si usa eso en la Adapteru otra clase, resultará en eso.

kaosmys
fuente
2

También tuve el mismo problema. Verifique todo el contexto que ha pasado. Para ' enlaces ' necesita un contexto de actividad, no un contexto de aplicación .

Este es el lugar donde debe verificar:

1.) Si utilizó LayoutInflater , compruebe qué contexto ha pasado.

2.) Si está utilizando un adaptador, verifique qué contexto ha pasado.

codemaniac
fuente
2

Yo tuve el mismo problema. El problema es con el contexto. Si desea abrir algún enlace (por ejemplo, compartir cualquier enlace a través del selector), pase el contexto de actividad, no el contexto de la aplicación.

No olvide agregar myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)si no está en su actividad.

Codificador29
fuente
2

Use este código en su Adaptador_Actividad y use context.startActivity(intent_Object)yintent_Object.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Me gusta esto:

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

Funciona....

Gaurav Lambole
fuente
1
Intent viewIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);    
viewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    
startActivity(viewIntent);   

Espero que esto funcione.

Chirag Patel
fuente
1

Enfrenté el mismo problema y luego lo implementé

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

y se resolvió el problema.

Puede haber otra razón relacionada con el adaptador de vista de lista.
Puedes ver este blog , lo describió muy bien.

Mayank Sharma
fuente
Blog útil, gracias. :)
Rucha Bhatt Joshi
1

Usa este código. Funciona bien para mi. Comparta algo desde fuera de una actividad:

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);
Pooya Hayati
fuente
Configuración de banderas desordenar el historial de stacktrace
Ezio
1

Dado que agregar indicadores afecta event_flowy stack_historyes mejor pasar el 'contexto de aplicación' a la no actividad desde donde necesita llamar a una clase de actividad de la siguiente manera:

"ActivityClassName.this" (Si bien pasa el contexto de esta manera, contendrá todos los detalles e información que necesita para llamar a una Actividad desde un escenario sin actividad)

Por lo tanto, no es necesario establecer o agregar indicadores, esto funcionará bien en todos los casos.

Musthafa
fuente
0
Intent i= new Intent(context, NextActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Chandan Lal
fuente
0

Si está invocando Compartir Intención en el complemento Cordova, establecer la Bandera no será de ayuda. En su lugar, use esto:

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

Mi situación era un poco diferente, estoy probando mi aplicación usando Espressoy tuve que iniciar mi Actividad con ActivityTestRulela instrumentación Context(que no es la que viene de un Activity).

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

Tuve que cambiar las banderas y agregar un orbit a bit ( |en Java) conIntent.FLAG_ACTIVITY_NEW_TASK

Entonces resulta en:

fun intent(context: Context) = 
    Intent(context, HomeActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
Rafael Ruiz Muñoz
fuente
0

Versión Kotlin

val intent = Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
this.startActivity(intent)
Sazzad Hissain Khan
fuente