PendingIntent/IntentSender介绍

2022-01-20  本文已影响0人  锄禾豆

前言

Android跨进程传递的前提为Parcelable对象或者binder对象,PendingIntent/IntentSender都满足,如下:
1)Parcelable
class PendingIntent implements Parcelable
class IntentSender implements Parcelable

2)核心都为IIntentSender mTarget,即binder对象

分析

PendingIntent,常见场景为通知或者Alarm定时器使用,而我们新安装接口采用PendingIntent监听安装状态情况,其原理分析如下:
案例:
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    InstallAppProgress.this /*context*/,
                    sessionId,
                    broadcastIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());//提交数据

详解:
1.获取Broadcast PendingIntent
    public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
            Intent intent, int flags, UserHandle userHandle) {
        String packageName = context.getPackageName();
        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
                context.getContentResolver()) : null;
        try {
            intent.prepareToLeaveProcess(context);
            IIntentSender target =
                ActivityManagerNative.getDefault().getIntentSender(
                    ActivityManager.INTENT_SENDER_BROADCAST, packageName,
                    null, null, requestCode, new Intent[] { intent },
                    resolvedType != null ? new String[] { resolvedType } : null,
                    flags, null, userHandle.getIdentifier());//binder(IIntentSender)对象由ActivityManagerService生成
            return target != null ? new PendingIntent(target) : null;//内部生成PendingIntent对象
        } catch (RemoteException e) {
        }
        return null;
    }
    
2.PendingIntent中创建的IntentSender对象
    public IntentSender getIntentSender() {
        return new IntentSender(mTarget);
    }
    
3.PackageInstaller.Session会话提交IntendSender
PackageInstaller.Session.commit --> PackageInstallerSession.commit

com.android.server.pm.PackageInstallerSession
    public void commit(IntentSender statusReceiver) {
        Preconditions.checkNotNull(statusReceiver);
        ···
        final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
                statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);//statusReceiver传递给了PackageInstallObserverAdapter
        mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();//handler发送消息,回调到adapter
    }
    
    
    static class PackageInstallObserverAdapter extends PackageInstallObserver {
        
        private final IntentSender mTarget;

        public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId,
                boolean showNotification, int userId) {
            ···
            mTarget = target;
            ···
        }
        ···
        @Override
        public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                Bundle extras) {
            ···
            final Intent fillIn = new Intent();
            fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
            fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
            fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
                    PackageManager.installStatusToPublicStatus(returnCode));
            fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
                    PackageManager.installStatusToString(returnCode, msg));
            fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
            if (extras != null) {
                final String existing = extras.getString(
                        PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
                if (!TextUtils.isEmpty(existing)) {
                    fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
                }
            }
            try {
                mTarget.sendIntent(mContext, 0, fillIn, null, null);//回调的消息,通过IntentSender发送出去
            } catch (SendIntentException ignored) {
            }
        }
    }
    
android.content.IntentSender
    public void sendIntent(Context context, int code, Intent intent,
            OnFinished onFinished, Handler handler, String requiredPermission)
            throws SendIntentException {
        try {
            String resolvedType = intent != null ?
                    intent.resolveTypeIfNeeded(context.getContentResolver())
                    : null;
            int res = ActivityManagerNative.getDefault().sendIntentSender(mTarget,
                    code, intent, resolvedType,
                    onFinished != null
                            ? new FinishedDispatcher(this, onFinished, handler)
                            : null,
                    requiredPermission, null);//ActivityManagerService处理Intent
            if (res < 0) {
                throw new SendIntentException();
            }
        } catch (RemoteException e) {
            throw new SendIntentException();
        }
    }
    
ActivityManagerService.sendIntentSender
    public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
            IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
        if (target instanceof PendingIntentRecord) {//PendingIntent生成的target都为PendingIntentRecord
            return ((PendingIntentRecord)target).sendWithResult(code, intent, resolvedType,
                    finishedReceiver, requiredPermission, options);
        } else {
            ····
        }
    }
注:target为PendingIntentRecord?关注PendingIntent生成PendingIntent对象的方法可知


PendingIntentRecord
1.class PendingIntentRecord extends IIntentSender.Stub  
也就是binder对象的服务端(IIntentSender.Stub)
2.sendWithResult --> sendInner
    final ActivityManagerService owner;
    
    int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
            String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
            int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
        ···
        synchronized (owner) {
            ···
            if (!canceled) {
                ···
                switch (key.type) {
                    case ActivityManager.INTENT_SENDER_ACTIVITY:
                        ···
                        try {
                            if (key.allIntents != null && key.allIntents.length > 1) {
                                ···
                                owner.startActivitiesInPackage(uid, key.packageName, allIntents,
                                        allResolvedTypes, resultTo, options, userId);
                            } else {
                                owner.startActivityInPackage(uid, key.packageName, finalIntent,
                                        resolvedType, resultTo, resultWho, requestCode, 0,
                                        options, userId, container, null);//执行activity
                            }
                        } catch (RuntimeException e) {
                            Slog.w(TAG, "Unable to send startActivity intent", e);
                        }
                        break;
                    case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
                        if (key.activity.task.stack != null) {
                            key.activity.task.stack.sendActivityResultLocked(-1, key.activity,
                                    key.who, key.requestCode, code, finalIntent);
                        }
                        break;
                    case ActivityManager.INTENT_SENDER_BROADCAST:
                        try {
                            // If a completion callback has been requested, require
                            // that the broadcast be delivered synchronously
                            int sent = owner.broadcastIntentInPackage(key.packageName, uid,
                                    finalIntent, resolvedType, finishedReceiver, code, null, null,
                                    requiredPermission, options, (finishedReceiver != null),
                                    false, userId);//执行广播
                            if (sent == ActivityManager.BROADCAST_SUCCESS) {
                                sendFinish = false;
                            }
                        } catch (RuntimeException e) {
                            Slog.w(TAG, "Unable to send startActivity intent", e);
                        }
                        break;
                    case ActivityManager.INTENT_SENDER_SERVICE:
                        try {
                            owner.startServiceInPackage(uid, finalIntent,
                                    resolvedType, key.packageName, userId);//执行服务
                        } catch (RuntimeException e) {
                            Slog.w(TAG, "Unable to send startService intent", e);
                        } catch (TransactionTooLargeException e) {
                            res = ActivityManager.START_CANCELED;
                        }
                        break;
                }

            
            }
        }
        return ActivityManager.START_CANCELED;
    }

总结

1.PendingIntent 通过 IntentSender 来到AMS,存储在PendingIntentRecord中。这里是IIntentSender客户端
2.PendingIntentRecord调用AMS执行广播/Activity/Service业务。这里是IIntentSender服务端
上一篇 下一篇

猜你喜欢

热点阅读