【Activity】 基于Android9.0的startActivity流程分析(1):原Activity的onPause流程

Android启动Activity流程解析

本文章基于Android9.0,测试demo为在一个已经启动的MainActivity中点击按钮通过调用startActivity启动SecondActivity,通过在源码中添加log定位分析整个流程。

启动操作:

startActivity(new Intent(this, SecondActivity.class));

其实在前台Activity中启动另一个Activity的过程主要分为以下几步:

  1. 原Activity的onPause
  2. 新Activity的onCreate
  3. 新Activity的onStart
  4. 新Activity的onResume
  5. 原Activity的onStop
  6. 原Activity的onSaveInstanceState

本文章也主要围绕这个几个流程来分析源码,如有不对之处,欢迎交流指正。

1. 原Activity的onPause流程

Demo是在继承在Activity的子类MainActivity中调用的startActivity,那么就看看Activity.startActivity函数。

[/frameworks/base/core/java/android/app/Activity.java]

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
     @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else { //执行else中的操作
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1); 
        }
    }

调用startActivityForResult。

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options); //调用Instrumentation.execStartActivity
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                .....
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            .....
        }
    }

接着来看Instrumentation.execStartActivity

[/framework/base/core/java/android/app/Instrumentation.java]

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
		
        ......
		
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);  //调用AMS.startActivity
            checkStartActivityResult(result, intent); //检查startActivity的结果
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
}

该函数主要完成的操作:

  • AMS.startActivity:启动新的Activity
  • checkStartActivityResult:检查新的Activity的启动结果,检查结束后,startActivity的调用也就结束了。

其中ActivityManager.getService()就是获取到AMS的句柄,然后调用AMS.startActivity。

[/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java]

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        enforceNotIsolatedCaller("startActivity");
        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
        // TODO: Switch to user app stacks here.
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
    }

其中mActivityStartController的声明:

private final ActivityStartController mActivityStartController;

mActivityStarterController.obtainStarter函数返回一个ActivityStarter对象:

[/frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java]

    /**
     * @return A starter to configure and execute starting an activity. It is valid until after
     *         {@link ActivityStarter#execute} is invoked. At that point, the starter should be
     *         considered invalid and no longer modified or used.
     */
    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    }

根据注释可以看到,在ActivityStarter.execute函数执行后才有效。结合AMS.startActivityAsUser函数,先设置各项参数,然后再调用ActivityStarter.execute执行后续的操作。接下里看看ActivityStarter.execute:

[/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java]

/**
     * Starts an activity based on the request parameters provided earlier.
     * @return The starter result.
     */
    int execute() {
        try {
            // TODO(b/64750076): Look into passing request directly to these methods to allow
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) {
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                        mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                        mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup);
            } else {
                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup);
            }
        } finally {
            onExecutionComplete();
        }
    }

因为之前的设置,mayWait = true,所以执行的startActivityMayWait,所以接着来看看这个函数。该函数比较长,仅阐述其中的关键流程:

private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
            int userId, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {
        ......
        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(); //提示Activity正在启动
        
		......

        synchronized (mService) {
            ......
            
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            //调用startActivity
            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);

            ...

            mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]); //提示Activity启动完成
            return res;
        }
    }
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {

        .....
		//调用startActivity,没有reason参数
        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                inTask, allowPendingRemoteAnimationRegistryLookup);

        if (outActivity != null) {
            // mLastStartActivityRecord[0] is set in the call to startActivity above.
            outActivity[0] = mLastStartActivityRecord[0];
        }

        return getExternalResult(mLastStartActivityResult);
    }
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
        int err = ActivityManager.START_SUCCESS;
        
		......//错误判断以及权限检测

        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity); //调用startActivity
    }
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
        int result = START_CANCELED;
        try {
            mService.mWindowManager.deferSurfaceLayout(); //暂停布局
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity); //关键函数
        } finally {
            // If we are not able to proceed, disassociate the activity from the task. Leaving an
            // activity in an incomplete state can lead to issues, such as performing operations
            // without a window container.
            final ActivityStack stack = mStartActivity.getStack();
            if (!ActivityManager.isStartResultSuccessful(result) && stack != null) { //如果启动失败的处理
                stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
                        null /* intentResultData */, "startActivity", true /* oomAdj */);
            }
            mService.mWindowManager.continueSurfaceLayout(); //继续布局
        }

        postStartActivityProcessing(r, result, mTargetStack);

        return result;
    }

该函数里主要的执行的操作:

  • WMS.deferSurfaceLayout:暂停布局
  • ActivityStarter.startActivityUnchecked:关键函数,启动Activity
  • WMS.continueSurfaceLayout:继续布局
  • ActivityStarter.postStartActivityPorcessing

看关键函数startActivityUnchecked,该函数较长,仅说明关键流程:

// Note: This method should only be called from {@link startActivity}.
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {

        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor); //初始化启动Activity的各种配置,会先重置再重新配置,其中包括ActivityRecord、Intent、TaskRecord和LaunchFlags(启动的FLAG)等等

        computeLaunchingTaskFlags(); //计算出启动的FLAG,并将计算的值赋值给mLaunchFlags

        computeSourceStack(); 

        mIntent.setFlags(mLaunchFlags);//将mLaunchFlags设置给Intent,达到设定Activity的启动方式的目的

        ActivityRecord reusedActivity = getReusableIntentActivity(); //获取可复用Activity

        ......

        if (reusedActivity != null) { //可复用Activity不为空
            ......
        }

        ......
		
        // Should this be considered a new task?
        int result = START_SUCCESS;
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
        } else if (mSourceRecord != null) { //根据Demo的情况,会执行这个if语句
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            result = setTaskFromInTask();
        } else {
            // This not being started from an existing activity, and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            setTaskToCurrentTopOrCreateNewTask();
        }
        if (result != START_SUCCESS) {
            return result;
        }

        ......
		
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                ......
            } else {
                // If the target stack was not previously focusable (previous top running activity
                // on that stack was not visible) then any prior calls to move the stack to the
                // will not update the focused stack.  If starting the new activity now allows the
                // task stack to be focusable, then ensure that we now update the focused stack
                // accordingly.
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
				
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);//关键函数
            }
        } else if (mStartActivity != null) {
            mSupervisor.mRecentTasks.add(mStartActivity.getTask());
        }
		
        ......

        return START_SUCCESS;
    }

private void computeLaunchingTaskFlags() {
      ...
      //如下code主要解决的问题就是Activity要加入的栈不存在时如何计算出启动的FLAG
      if (mInTask == null) {//mInTask为null,说明Activity要加入的栈不存在
            if (mSourceRecord == null) {//源Activity,即启动待启动Activity的Activity。如ActivityA启动了ActivityB,那么ActivityA就是源Activity
                if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {//条件满足则创建一个新栈
                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
                    mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
                }
            } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {//如果源Activity所在的栈只允许有一个实例,也需要创建一个新栈
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            } else if (mLaunchSingleInstance || mLaunchSingleTask) {//如果LaunchMode设置了singleTask或singleInstance,则也要创建一个新栈
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            }
        }
}

该函数主要完成的操作:

  • ActivityStarter.setInitialState
  • ActivityStarter.computeLaunchingTaskFlags
  • ActivityStarter.computeSourceTask
  • ActivityStarter.getResuableIntentActivity
  • ActivityStarter.setTaskFromSourceRecord
  • ActivityStackSupervisor.resumeFocusedStackTopActivityLocked:关键函数

来看看关键函数resumeFocusedStackTopActivityLocked:

// /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        ......

        if (targetStack != null && isFocusedStack(targetStack)) { //执行该条件
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }

        ......

        return false;
    }

主要完成的操作是调用ActivityStack.resumeTopActivityUncheckedLocked函数:

// /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
@GuardedBy("mService")
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        ...
		
        try {
            ......
			
            result = resumeTopActivityInnerLocked(prev, options);

            ...
			
            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }

        return result;
    }

主要完成的操作:

  • ActivityStack.resumeTopActivityInnerLocked:关键函数
  • ActivityStack.topRunningActivityLocked

看看关键函数resumeTopActivityInnerLocked,该函数较长,主要的操作是ActivityStack.startPausingLocked:

@GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ......

    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
    if (mResumedActivity != null) {
         pausing |= startPausingLocked(userLeaving, false, next, false);
    }

    ......
}

startPausingLocked函数就是将原Activity进行pause操作:

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {
        ...

        if (prev.app != null && prev.app.thread != null) {
            try {
                ...
				
                mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                        PauseActivityItem.obtain(prev.finishing, userLeaving,
                                prev.configChangeFlags, pauseImmediately));  //关键操作
            } catch (Exception e) {
                .....
            }
        } else {
            ...
        }
		
		...
    }

此处的mService是指的AMS,mService.getLifecycleManager()获取了ClientLifecycleManager对象。ClientLifecycleManaer.sheduleTransaction函数管控了Activity的生命周期函数的执行。

// /frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java     
    /**
     * Schedule a single lifecycle request or callback to client activity.
     * @param client Target client.
     * @param activityToken Target activity token.
     * @param stateRequest A request to move target activity to a desired lifecycle state.
     * @throws RemoteException
     *
     * @see ClientTransactionItem
     */
    void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
            @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
        final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
                stateRequest);
        scheduleTransaction(clientTransaction);
    }

其中的stateRequest参数就是上文的PauseActivityItem对象。该函数中完成的主要操作:

  • transactionWithState
    /**
     * @return A new instance of {@link ClientTransaction} with a single lifecycle state request.
     *
     * @see ClientTransaction
     * @see ClientTransactionItem
     */
    private static ClientTransaction transactionWithState(@NonNull IApplicationThread client,
            @NonNull IBinder activityToken, @NonNull ActivityLifecycleItem stateRequest) {
        final ClientTransaction clientTransaction = ClientTransaction.obtain(client, activityToken);
        clientTransaction.setLifecycleStateRequest(stateRequest);
        return clientTransaction;
    }

将PauseActivityItem对象设置到clientTransaction对象中。并返回该clientTransaction对象。

  • scheduleTransaction
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule(); //调用ClientTransaction的schedule函数
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }
    }

接下来看看ClientTransaction.schedule函数:

// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
    
    private IApplicationThread mClient;

    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }

mClient实质就是应用进程与系统进程(system_server)通信的服务端,即ActivityThread.ApplicaitonThread对象。所以接下来调用到了ActivityThread.ApplicationThread.sheduleTransaction函数:

// /frameworks/base/core/java/android/app/ActivityThread.java
        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }

ActivityThread中没有定义函数scheduleTransaction,因为ActivityThread继承于ClientTransactionHandler,所以查看ActivityThread的父类中该函数。

// /frameworks/base/core/java/android/app/ClientTransactionHandler.java
    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
    
    abstract void sendMessage(int what, Object obj);

sendMessage为抽象函数,ActivityThread实现了该函数。所以此处又调用到了ActivityThread.sendMessage函数中:

 ///frameworks/base/core/java/android/app/ActivityThread.java
    void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

其中的mH为ActivityThread内部类H的一个对象,用于处理Message。此前通过sendMessage发送的消息为H.EXECUTE_TRANSACTION,所以来看看mH是如何处理这个消息的。

// /frameworks/base/core/java/android/app/ActivityThread.java
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);

//ActivityThread.H的handleMessage函数
case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    mTransactionExecutor.execute(transaction);
    if (isSystem()) {
        // Client transactions inside system process are recycled on the client side
        // instead of ClientLifecycleManager to avoid being cleared before this
        // message is handled.
        transaction.recycle();
    }
    // TODO(lifecycler): Recycle locally scheduled transactions.
    break;                

接下来看看TransactionExecutor.execute函数做了些什么:

    /**
     * Resolve transaction.
     * First all callbacks will be executed in the order they appear in the list. If a callback
     * requires a certain pre- or post-execution state, the client will be transitioned accordingly.
     * Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
     * either remain in the initial state, or last state needed by a callback.
     */
    public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

        executeCallbacks(transaction);

        executeLifecycleState(transaction);
        mPendingActions.clear();
        log("End resolving transaction");
    }

execute函数中主要完成的操作是:

  • executeCallbacks:因为此前没有传入callback,所以callback为空,未做任何实际的操作。
  • executeLifecycleState
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
    /** Transition to the final state if requested by the transaction. */
    private void executeLifecycleState(ClientTransaction transaction) {
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest(); //根据前文描述,lifecycleItem就是PauseActivityItem对象
        if (lifecycleItem == null) {
            // No lifecycle request, return early.
            return;
        }
        log("Resolving lifecycle state: " + lifecycleItem);

        final IBinder token = transaction.getActivityToken();
        final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

        if (r == null) {
            // Ignore requests for non-existent client records for now.
            return;
        }

        // Cycle to the state right before the final requested state.
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

        // Execute the final transition with proper parameters.
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }

即该函数中主要完成的操作:(1) cycleToPath ; (2)PauseActivityitem.execute ; (3) PauseActivityItem.postExecute。接着来分析一下这三个过程。

  • cycleToPath
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
    private void cycleToPath(ActivityClientRecord r, int finish,
            boolean excludeLastState) {
        final int start = r.getLifecycleState();
        log("Cycle from: " + start + " to: " + finish + " excludeLastState:" + excludeLastState);
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
        performLifecycleSequence(r, path);
    }

根据demo的case情况,path.size = 0,所以performLifecycleSequence函数并未执行任何操作。

  • PauseActivityItem.execute
// /frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java
    @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
        client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
                "PAUSE_ACTIVITY_ITEM");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

关键的操作就是调用了ClientTransactionHandler.handlePauseActivity,而在ClientTransactionHandler类中,handlePauseActivity是个抽象函数,其实现在ActivityThread类中。也即是此处调用了ActivityThread.handlePauseActivity。

///frameworks/base/core/java/android/app/ActivityThread.java
	@Override
    public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
            int configChanges, PendingTransactionActions pendingActions, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(r, finished, reason, pendingActions);

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }
            mSomeActivitiesChanged = true;
        }
    }

继续调用ActivityThread.performPauseActivity

private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
            PendingTransactionActions pendingActions) {
        ...

        // Pre-Honeycomb apps always save their state before pausing
        final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb(); //值为false
        if (shouldSaveState) {
            callActivityOnSaveInstanceState(r);
        }

        performPauseActivityIfNeeded(r, reason);

        ...

        return shouldSaveState ? r.state : null;
    }

再看看performPauseActivityIfNeeded:

    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        if (r.paused) {
            // You are already paused silly...
            return;
        }

        try {
            r.activity.mCalled = false;
            mInstrumentation.callActivityOnPause(r.activity);  //关键操作
            if (!r.activity.mCalled) {
                throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
                        + " did not call through to super.onPause()");
            }
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException("Unable to pause activity "
                        + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
            }
        }
        r.setState(ON_PAUSE);
    }

又调用了Instrumentation.callActivityOnPause函数:

// /frameworks/base/core/java/android/app/Instrumentation.java
	/**
     * Perform calling of an activity's {@link Activity#onPause} method.  The
     * default implementation simply calls through to that method.
     *
     * @param activity The activity being paused.
     */
    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }	

又调用了Activity的performPause函数:

// /frameworks/base/core/java/android/app/Activity.java
    final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause(); //处理Fragment的pause操作
        mCalled = false;
        onPause();  //执行onPause函数
        writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause");
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
    }

至此,原Activity的onPause函数得到了执行

在此总结一下该流程,因为调用层次较深,所以使用了一个思维导图来描述调用层次。

  • PauseActivityItem.postExecute

该函数涉及到了新的Activity的启动流程,后续再接着分析。先看一下该函数的code。

    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        if (mDontReport) {
            return;
        }
        try {
            // TODO(lifecycler): Use interface callback instead of AMS.
            ActivityManager.getService().activityPaused(token); //跨进程调用AMS.activityPaused函数
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

<think>我们正在解决Android中自定义广播和Location接收失效的问题。根据用户的问题描述和提供的引用,我们可以分析可能的因和解决方案。首先,关于自定义广播接收失效的可能因:1.**广播注册方式**:在Android8.0(API26)及以上版本,对隐式广播的使用进行了限制。如果自定义广播是隐式的(即没有指定接收者的包名或类名),则可能无法被接收。2.**广播注册位置**:广播接收器需要在AndroidManifest.xml中静态注册,或者在代码中动态注册。如果注册方式不正确,可能导致接收不到。3.**广播发送方式**:发送广播时,如果使用了不正确的Intent,或者没有设置ComponentName(对于显式广播),也可能导致接收不到。4.**权限问题**:发送或接收广播时可能需要权限,如果没有声明或请求权限,可能导致失败。其次,关于Location接收失效的可能因:1.**权限问题**:从Android6.0(API23)开始,获取位置信息需要动态请求运行时权限(ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION)。2.**位置服务未开启**:用户可能关闭了设备的位置服务。3.**位置提供器的选择**:在请求位置更新时,可能指定的位置提供器(如GPS或网络)不可用。4.**省电模式**:设备的省电模式可能会限制后台位置更新。5.**后台限制**:在Android8.0及以上版本,对后台应用获取位置信息进行了限制。参考提供的引用:引用[1]提到在Android9.0中,一些网络相关的函数和广播不再接收用户位置或个人可识别数据。因此,在Android9.0及以上版本,即使应用拥有位置权限,某些广播也可能无法携带位置信息。引用[2]展示了一个短信广播接收器的例子,其中使用了abortBroadcast()来阻断广播。但注意,在Android4.4及以上版本,有序广播的优先级设置和abortBroadcast()的使用可能受到限制,特别是对于系统广播(如短信广播)可能不再允许应用拦截。引用[3]提到了调试标记开启的安全风险,但这与广播和位置接收失效关系不大。引用[4]比较了SurfaceView和TextureView,与当前问题无关。因此,我们重点分析广播和位置接收失效的因,并给出解决方案。解决方案:一、自定义广播接收失效的解决方案:1.**使用显式广播**:针对自定义广播,建议使用显式广播,即在发送广播时指定接收者的ComponentName(包名和类名)。这样不受隐式广播限制的影响。2.**静态注册注意事项**:如果需要在应用未启动时接收广播,可以静态注册。但注意,Android8.0及以上版本对静态注册的隐式广播有限制,所以对于自定义广播,建议使用显式意图。同时,在AndroidManifest.xml中声明接收器时,需要设置exported属性(如果只接收应用内广播,可设为false)。3.**动态注册广播**:在Activity或Service中动态注册广播接收器,并确保在合适的生命周期方法中注销。4.**权限设置**:如果广播涉及到权限,需要在发送和接收时声明相同的权限。例如,在发送广播时使用`sendBroadcast(intent,permission)`,接收方在注册时也需要声明该权限。二、位置接收失效的解决方案:1.**检查权限**:确保在AndroidManifest.xml中声明了所需的位置权限(ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION),并且在运行时(Android6.0及以上)动态请求权限。2.**检查位置服务是否开启**:在请求位置更新前,检查设备的位置服务是否开启。如果没有开启,可以引导用户打开。3.**选择合适的定位提供器**:使用LocationManager的`getProviders()`方法获取可用的提供器,或者使用FusedLocationProviderClient(GooglePlay服务的一部分)来获取位置,它会自动选择最佳的提供器。4.**处理后台位置限制**:对于Android8.0及以上版本,后台应用接收位置更新的频率会受到限制。如果需要持续获取位置,可以考虑使用前台服务,并显示一个持续的通知。5.**省电模式处理**:检查设备是否处于省电模式,并考虑在省电模式下调整位置更新策略(如降低更新频率)。代码示例:自定义广播发送和接收(显式广播):发送广播(在Activity或Service中):```javaIntentintent=newIntent();intent.setAction("com.example.MY_CUSTOM_ACTION");//显式设置接收者intent.setComponent(newComponentName("com.example.receiverapp","com.example.receiverapp.MyBroadcastReceiver"));sendBroadcast(intent);```接收器(静态注册在AndroidManifest.xml中):```xml<receiverandroid:name=".MyBroadcastReceiver"android:enabled="true"android:exported="true"><!--如果只接收本应用广播,exported可设为false,但显式广播通常不受影响--><intent-filter><actionandroid:name="com.example.MY_CUSTOM_ACTION"/></intent-filter></receiver>```动态注册广播接收器(在Activity中):```javaprivateBroadcastReceivermReceiver=newBroadcastReceiver(){@OverridepublicvoidonReceive(Contextcontext,Intentintent){//处理广播}};@OverrideprotectedvoidonResume(){super.onResume();IntentFilterfilter=newIntentFilter("com.example.MY_CUSTOM_ACTION");registerReceiver(mReceiver,filter);}@OverrideprotectedvoidonPause(){super.onPause();unregisterReceiver(mReceiver);}```位置请求示例(使用FusedLocationProviderClient):1.添加依赖(build.gradle):implementation&#39;com.google.android.gms:play-services-location:18.0.0&#39;2.请求位置更新:```javaFusedLocationProviderClientfusedLocationClient=LocationServices.getFusedLocationProviderClient(this);//检查权限if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){//创建位置请求LocationRequestlocationRequest=LocationRequest.create();locationRequest.setInterval(10000);//更新间隔locationRequest.setFastestInterval(5000);//最快更新间隔locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);//请求位置更新fusedLocationClient.requestLocationUpdates(locationRequest,locationCallback,null);}else{//请求权限ActivityCompat.requestPermissions(this,newString[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_LOCATION_PERMISSION);}//定义位置回调privateLocationCallbacklocationCallback=newLocationCallback(){@OverridepublicvoidonLocationResult(LocationResultlocationResult){if(locationResult==null){return;}for(Locationlocation:locationResult.getLocations()){//处理位置更新}}};//在合适的时机移除更新请求(如onDestroy)@OverrideprotectedvoidonDestroy(){super.onDestroy();fusedLocationClient.removeLocationUpdates(locationCallback);}```注意事项:-在AndroidManifest.xml中声明位置权限:```xml<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/><!--或者使用ACCESS_COARSE_LOCATION-->```总结:1.自定义广播失效:优先使用显式广播,注意注册方式和权限。2.位置接收失效:检查权限、位置服务状态,并适配不同Android版本的后台限制。如果问题仍然存在,请检查系统版本和日志,以获取更详细的错误信息。生成相关问题:§§相关问题§§1.Android8.0及以上版本对广播有哪些限制?2.如何动态请求位置权限?3.Android9.0及以上版本,如何获取后台位置更新?4.使用FusedLocationProviderClient有哪些优势?</think>### Android 自定义广播与位置接收失效解决方案 #### 一、自定义广播失效因及修复 1. **Android 8.0+ 隐式广播限制** ```java // 错误:隐式广播(Android 8.0+ 将被系统屏蔽) Intent intent = new Intent("com.example.MY_CUSTOM_ACTION"); sendBroadcast(intent); // 正确:显式广播(指定目标组件) Intent intent = new Intent("com.example.MY_CUSTOM_ACTION"); intent.setComponent(new ComponentName("com.example.pkg", "com.example.Receiver")); sendBroadcast(intent); ``` - **因**:Android 8.0+ 禁止大部分隐式广播[^1] - **修复**: - 使用显式广播(指定目标包名/类名) - 对于应用内广播:使用 `LocalBroadcastManager` 2. **广播接收器注册问题** ```xml <!-- AndroidManifest.xml 静态注册 --> <receiver android:name=".MyReceiver" android:exported="true"> <intent-filter> <action android:name="com.example.MY_CUSTOM_ACTION" /> </intent-filter> </receiver> ``` - **动态注册未注销**:导致内存泄漏和接收失效 ```java // Activity 中动态注册/注销 @Override protected void onResume() { super.onResume(); registerReceiver(receiver, new IntentFilter("MY_ACTION")); } @Override protected void onPause() { super.onPause(); unregisterReceiver(receiver); // 必须注销 } ``` 3. **权限问题** ```xml <!-- 发送带权限的广播 --> <uses-permission android:name="com.example.PERMISSION" /> <!-- 接收器声明权限 --> <receiver android:name=".MyReceiver" android:permission="com.example.PERMISSION"> ``` - 发送/接收端需声明相同权限[^2] #### 二、位置接收失效因及修复 1. **Android 9.0+ 位置权限变更** ```java // 必须同时请求前台和后台权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { requestPermissions(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION // 后台权限 }, REQUEST_CODE); } ``` - **因**:Android 9.0+ 限制后台位置访问[^1] - **修复**: - 动态请求 `ACCESS_BACKGROUND_LOCATION` - 在 `AndroidManifest.xml` 声明: ```xml <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> ``` 2. **位置服务未启用** ```java // 检查位置服务状态 LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE); if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { // 引导用户开启位置服务 startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); } ``` 3. **省电模式限制** ```java // 检查省电模式 PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (pm.isDeviceIdleMode()) { // 处理省电模式下的位置获取策略 } } ``` #### 三、通用解决方案 1. **生命周期管理** - 在 `onStart()`/`onResume()` 注册接收器 - 在 `onStop()`/`onPause()` 注销接收器 - 使用 `LifecycleObserver` 自动管理 2. **后台限制处理** ```java // 使用前台服务获取后台位置 public class LocationService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(NOTIFICATION_ID, createNotification()); // 启动位置监听 return START_STICKY; } } ``` 3. **广播发送优化** ```java // 使用带权限的广播发送 sendBroadcast(intent, "com.example.PERMISSION"); // 使用有序广播传递数据 sendOrderedBroadcast(intent, null, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 处理最终结果 } }, null, RESULT_OK, null, null); ``` #### 四、适配建议 | 系统版本 | 广播策略 | 位置策略 | |----------|----------|----------| | Android 7.0- | 隐式广播可用 | 只需前台权限 | | Android 8.0-9 | 显式广播 | 需后台权限声明 | | Android 10+ | 组件显式注册 | 后台访问需用户手动授权 | > **关键点**:从 Android 10 开始,后台位置访问需在设置中单独开启,应用需引导用户操作: > ```java > Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); > intent.setData(Uri.parse("package:" + getPackageName())); > startActivity(intent); > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值