なぜAndroid 7.0と8.0でApplicationContext.startActivty(...)FLAG_を追加する必要はありませんACTIVITY_NEW_TASKは?

13334 ワード

Android 7では0より前に、Activity以外の環境(ApplicationContextなど)でActivityを起動するにはFLAG_を追加する必要があります.ACTIVITY_NEW_TASKタグビットは、Activityが正常に起動します.Activity以外の環境にはいわゆるタスクスタックはないからです.
しかし、最近プロジェクトで発見されたのはAndroid 7.0と8.0にFLAG_を追加する必要はありませんACTIVITY_NEW_TASKタグビットはAndroid 9で正常に起動することもできる.0の公式文書にまた強制的に追加されました.公式サイトがどう言っているか見てみましょう.
Android 9では、IntentフラグFLAG_を渡さない限り、Activity以外の環境からActivityを起動することはできません.ACTIVITY_NEW_TASK.このフラグを渡さずにActivityを起動しようとすると、Activityは起動せず、ログにメッセージが出力されます.Android 7.0までは、ロゴ要求は常に所望の行為であり、強制的に実行されていた.Android7.0のエラーの1つは、実装フラグ要件を一時的にブロックします.
最後の一言を見てください.「Android 7.0のエラーは、実装フラグの要求を一時的に阻止します」.もしかしてグーグルのバグ?ソースコード(frameworks/base/core/java/android/app/ClontextImpl.java)を見てみましょう.
  • まずAndroid 6を見てみましょう.0の表記
  • @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
    
  • Android 7.0~Android8.0
  •  @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
    
        // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
        // generally not allowed, except if the caller specifies the task id the activity should
        // be launched in.
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && 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?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
    
    
  • Android 9.0以上がこの問題を修復し、
  • を強制執行した.
    @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
    
        // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
        // generally not allowed, except if the caller specifies the task id the activity should
        // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
        // maintain this for backwards compatibility.
        final int targetSdkVersion = getApplicationInfo().targetSdkVersion;
    
        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?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
    

    Android 7.0-8.0の中にoptionsが入っています!=nullの判断では、optionsはBundleタイプであり、正常にActivityを起動してBundleを伝えなければ異常注意を投げ出すことはない.その後Android 9.0でまたoptions==nullに変更されました.