web-dev-qa-db-ja.com

アクティビティの外部からstartActivity()を呼び出しますか?

AlarmManagerを使用して、信号をブロードキャストするインテントをトリガーしています。以下は私のコードです:

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

この変数をActivityから呼び出しているので、次のエラーがどのように発生するかわかりません...

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

AndroidバージョンがAndroid-6未満の場合、この行を追加する必要があります。そうしないと、Android-6より上で動作します。

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

同じアクティビティの複数インスタンスの場合、次のスニペットを使用します。

:このスニペットは、Activity以外で使用しています。 AndroidManifestファイルにAndroid:launchMode="singleTop|singleInstance"が含まれていないことを確認してください。必要に応じて、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);

これは私には問題ありません。これが誰かの時間を節約することを願っています。誰かがより良い方法を見つけたら、私たちと共有してください。

51
Nandagopal T

Android Doc 言う-

FLAG_ACTIVITY_NEW_TASK要件が実施されました

Android 9では、インテントフラグFLAG_ACTIVITY_NEW_TASKを渡さない限り、非アクティビティコンテキストからアクティビティを開始できません。このフラグを渡さずにアクティビティを開始しようとすると、アクティビティは開始されず、システムはログにメッセージを出力します。

注:フラグの要件は常に意図された動作であり、Android 7.0(APIレベル24)よりも低いバージョンで適用されました。 Android 7.0のバグにより、フラグ要件が適用されませんでした。

つまり、(Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)の場合、Activityコンテキストの外部からstartActivity()を呼び出しているときにIntent.FLAG_ACTIVITY_NEW_TASKを追加する必要があります。

したがって、すべてのバージョンにフラグを追加することをお勧めします-

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

startActivityを呼び出す部分は貼り付けませんでした。これは興味深い部分です。

startActivityコンテキストまたはServiceコンテキストでApplicationを呼び出している可能性があります。

startActivity呼び出しを行う前にcatをログに記録するために "this"を出力し、それが何を参照しているかを確認します。

12
marmor

このエラーは、startActivity(...)を明示的に呼び出さなくても発生する場合があります。たとえば、一部のユーザーは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)

トレースにはフレームワークコードしか含まれていないため、何が間違っているのか疑問に思うかもしれません。さて、これがどのように起こるかの例です。私たちがフラグメントにいるとしましょう。

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

これで、ユーザーがそのテキストビューをクリックすると、上記のスタックトレースでアプリがクラッシュします。これは、layout inflaterapplication contextへの参照があるため、text viewにアプリケーションコンテキストがあるためです。そのテキストビューをクリックすると暗黙的にappContext.startActivity(...)を呼び出します。

最後のメモ:Android 4、5、6、および7デバイスでこれをテストしました。 4、5、および6にのみ影響します。Android 7デバイスは、appContext.startActivity(...)を呼び出すのに問題がないようです。

これが他の誰かに役立つことを願っています!

8
AutonomousApps

アプリケーションコンテキスト(つまり、getApplication(); getApplicationContext();)の代わりに、この場合はアクティビティコンテキストを使用する必要があります---> YourActivity.this

1

次の行に変更してみてください。

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

アクティビティの外部からのstartActivityが一部のAndroidバージョン(NとO-MR1の間)で有効であり、興味深い点はAndroidソースのバグであることに注意してください。コード!


これは、startActivity実装の上のコメントです。 here を参照してください。

FLAG_ACTIVITY_NEW_TASKを使用せずにアクティビティの外部から開始アクティビティを呼び出すことは、呼び出し元がアクティビティを起動するタスクIDを指定している場合を除き、通常は許可されません。これは動作します

0
Fartab

アプリ内でアクティビティを開く場合は、パラメーターとしてIntentを指定してstartActivity()メソッドを呼び出すことができます。その意図は、開きたいアクティビティになります。最初に、コンテキストとなる最初のパラメーターとターゲットアクティビティクラスとなる2番目のパラメーターを使用して、その目的のオブジェクトを作成する必要があります。

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

これが役立つことを願っています。

0