前言
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服务端
网友评论