Chamando startActivity () de fora de uma Atividade?

196

Estou usando um AlarmManagerpara acionar uma intenção que transmite um sinal. O seguinte é o meu código:

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

Estou chamando esse código de um Activity, então não sei como poderia estar recebendo o seguinte erro ...

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
fonte

Respostas:

494

se a sua versão do Android estiver abaixo do Android - 6, você precisará adicionar esta linha, caso contrário, ela funcionará acima do Android - 6.

...
Intent i = new Intent(this, Wakeup.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
Cristian
fonte
8
sim isso funciona. mas se você deseja iniciar várias instâncias da mesma atividade, isso não funciona. Como o FLAG_ACTIVITY_NEW_TASK retomará a mesma atividade existente
Ovidiu Latcu
7
Adicionar sinalizador FLAG_ACTIVITY_Multiple_TASKS PARA RESOLVER O SEU Problema
Pavankumar Vijapur
Cuidado, você precisa disso no Android 9+ também, veja esta resposta para obter esclarecimentos
Vadim Kotov
55

Para várias instâncias da mesma atividade, use o seguinte trecho,

Nota : estou usando este trecho fora do meu Activity. Verifique se o seu AndroidManifestarquivo não contém android:launchMode="singleTop|singleInstance". se necessário, você pode alterá-lo para 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);

Este trabalho é bom para mim. Espero que isso economize tempo para alguém. Se alguém encontrar uma maneira melhor, compartilhe conosco.

Nandagopal T
fonte
5
Por favor, entenda a diferença entre os métodos setFlags () e addFlag (). Tudo o que você está fazendo agora é iniciar uma atividade com FLAG_ACTIVITY_NEW_TASK. Como no código postado por Cristian abaixo.
21412 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);
21412 JehandadK
42

O Doc Android diz:

O requisito FLAG_ACTIVITY_NEW_TASK agora é imposto

Com o Android 9, você não pode iniciar uma atividade a partir de um contexto de não atividade, a menos que passe o sinalizador de intenção FLAG_ACTIVITY_NEW_TASK. Se você tentar iniciar uma atividade sem passar esse sinalizador, a atividade não será iniciada e o sistema imprimirá uma mensagem no log.

Nota: o requisito de sinalização sempre foi o comportamento pretendido e foi imposto em versões inferiores ao Android 7.0 (nível 24 da API). Um bug no Android 7.0 impedia que o requisito de sinalizador fosse imposto.

Isso significa (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)que é obrigatório adicionar Intent.FLAG_ACTIVITY_NEW_TASKao chamar startActivity()de fora de um Activitycontexto.

Portanto, é melhor adicionar sinalizador para todas as versões -

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

Você não colou a parte onde chama startActivity , essa é a parte interessante.

Você pode estar chamando startActivityem um Servicecontexto ou em um Applicationcontexto.

Imprima "this" para registrar o gato antes de fazer a startActivitychamada e veja a que se refere; às vezes, é possível usar um "this" interno acidentalmente.

marmor
fonte
1
Provavelmente, o problema está ocorrendo no OP. Eu encontrei o mesmo. Iniciar uma atividade com getApplicationContext () em vez de uma atividade existente acionará esse erro.
Hazen Hills Software
AGRADÁVEL :) Tenho certeza de que esse foi o erro que tento detectar a noite toda. Obrigado, senhor.
Martin Pfeffer
9

Às vezes, esse erro pode ocorrer sem uma chamada explícita para startActivity(...). Por exemplo, alguns de vocês podem ter visto um rastreamento de pilha como este no 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)

E você pode se perguntar o que fez de errado, pois o rastreamento inclui apenas o código da estrutura. Bem, aqui está um exemplo de como isso pode acontecer. Digamos que estamos em um fragmento.

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!!

Agora, quando um usuário clica na exibição de texto, seu aplicativo trava com o rastreamento de pilha acima. Isso ocorre porque o inflator de layout tem uma referência ao contexto do aplicativo e, portanto, sua visualização de texto possui um contexto de aplicativo. Clicar nessa visualização de texto chama implicitamenteappContext.startActivity(...) .

Nota final: testei isso em dispositivos Android 4, 5, 6 e 7. Afeta apenas 4, 5 e 6. Os dispositivos Android 7 aparentemente não têm problemas para ligar appContext.startActivity(...).

Espero que isto ajude alguém!

AutonomousApps
fonte
2

Este mesmo erro eu enfrentei no caso de receber uma notificação nos dispositivos Android mais recentes 9 e 10.

Depende do modo de inicialização como você está lidando com isso. Use o código abaixo: - android: launchMode = "singleTask"

Adicione este sinalizador com Intent: - intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);

Puneet Kumar
fonte
1

Tente mudar para esta linha:

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

Eu só quero perceber que startActivity de fora uma atividade é válida em algumas versões do Android (entre N e O-MR1) e o ponto interessante é que é um bug no código-fonte do Android!


Este é o comentário acima da startActivityimplementação. Veja aqui .

Chamar a atividade inicial de fora de uma atividade sem FLAG_ACTIVITY_NEW_TASK geralmente não é permitido, exceto se o chamador especificar o ID da tarefa na qual a atividade deve ser iniciada. Havia um bug entre N e O-MR1 que permitia que isso funcionasse .

Fartab
fonte
qual é a solução para isso
dominic_torreto 15/01
0

Quando você deseja abrir uma atividade no seu aplicativo, pode chamar o método startActivity () com um Intent como parâmetro. Essa intenção seria a atividade que você deseja abrir. Primeiro, você deve criar um objeto dessa intenção com o primeiro parâmetro para ser o contexto e o segundo parâmetro para a classe de atividade de destino.

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

Espero que isso ajude.

Mestre Shafiqur Rahman
fonte
3
Estou escrevendo como revisor porque sua resposta foi sinalizada como de baixa qualidade. A desvantagem dessa resposta é que não há explicação sobre o que seu código faz ou por que ele resolve o problema colocado na pergunta. Você poderia adicionar alguns comentários explicativos, tendo em mente que muitos programadores poderão ler sua resposta no futuro para obter orientação. Obrigado!
Bill Sino
Quando você deseja abrir uma atividade no seu aplicativo, pode chamar o método startActivity () com um Intent como parâmetro. Essa intenção seria a atividade que você deseja abrir. Primeiro, você deve criar um objeto dessa intenção com o primeiro parâmetro para ser o contexto e o segundo parâmetro para a classe de atividade de destino. Espero que isso ajude.
Dr. Shafiqur Rahman
ESTÁ BEM. Mas, em vez de colocar essas informações em um comentário, você deve editar sua resposta e colocá-la lá. Lamento não comentar este ponto, mas é importante fazer isso para todas as respostas. Cumprimentos.
Bill Sino
Sim, inclua explicações sobre por que sua resposta está correta. Apenas aprendemos a ser melhores programadores quando aprendemos POR QUE fazemos as coisas que fazemos.
kiwicomb123