用到的代码文件
frameworks/base/core/java/:
android/content/Intent.java
com/android/internal/app/ChooserActivity.java
com/android/internal/app/ResolverActivity.java
com/android/internal/app/ResolverListController.java
代码执行流程图
系统分享界面启动流程
下面的代码基于android O(api 27)。
本文基于MTK(MediaTek)平台基线。
本文主要记录公司某文件管理器app中点击某个文件进行分享的流程,因此并不适用于所有android系统分享界面的启动流程,具体问题须对照源码具体分析,但是思路基本一致。
当在应用上点击share按钮的时候首先调用Intent类中createChooser()这个方法。
public static Intent createChooser(Intent target,
CharSequence title) {
/*target: Intent { act=android.intent.action.SEND
typ=application/vnd.android.package-archive
flg=0x3 (has extras) } title: Share file(s) via*/
Log.w("Intent", "method createChooser() target: "
+ target + " title: " + title);
return createChooser(target, title, null);
}
接下来调用Intent.java中的createChooser()重载方法。
public static Intent createChooser(Intent target,
CharSequence title, IntentSender sender) {
/*method createChooser() target:
Intent { act=android.intent.action.SEND
typ=application/vnd.android.package-archive
flg=0x3 (has extras) } title: Share file(s)
viasender: null*/
log("method createChooser() target: " + target
+ " title: " + title + "sender: " + sender);
Intent intent = new Intent(ACTION_CHOOSER);
intent.putExtra(EXTRA_INTENT, target);
if (title != null) {// -> true
intent.putExtra(EXTRA_TITLE, title);
}
if (sender != null) { // -> false
intent.putExtra(EXTRA_CHOSEN_COMPONENT_INTENT_SENDER,
sender);
}
// Migrate any clip data and flags from target.
int permFlags = target.getFlags()
& (FLAG_GRANT_READ_URI_PERMISSION
| FLAG_GRANT_WRITE_URI_PERMISSION
| FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| FLAG_GRANT_PREFIX_URI_PERMISSION);
if (permFlags != 0) {
//permFlags: 3
log("permFlags: "+permFlags);
ClipData targetClipData = target.getClipData();
if (targetClipData == null && target.getData() != null) {
// -> false
ClipData.Item item = new ClipData.Item(target.getData());
String[] mimeTypes;
if (target.getType() != null) {
mimeTypes = new String[] { target.getType() };
} else {
mimeTypes = new String[] { };
}
targetClipData = new ClipData(null, mimeTypes, item);
}
if (targetClipData != null) {// -> false
intent.setClipData(targetClipData);
intent.addFlags(permFlags);
}
}
return intent;
}
至此启动ChooserActivity的Intent构造完成,下面进入ChooserActivity的onCreate()方法中。
@Override
protected void onCreate(Bundle savedInstanceState) {
log("method onCreate()");
final long intentReceivedTime = System.currentTimeMillis();
mIsSuccessfullySelected = false;
Intent intent = getIntent();
Parcelable targetParcelable =
intent.getParcelableExtra(Intent.EXTRA_INTENT);
if (!(targetParcelable instanceof Intent)) {// -> false
Log.w("ChooserActivity", "Target is not an intent: "
+ targetParcelable);
finish();
super.onCreate(null);
return;
}
Intent target = (Intent) targetParcelable;
if (target != null) {// -> true
//修改target intent的启动flag
modifyTargetIntent(target);
}
Parcelable[] targetsParcelable
= intent.getParcelableArrayExtra(
Intent.EXTRA_ALTERNATE_INTENTS);
if (targetsParcelable != null) { // -> false
......
}
mReplacementExtras = intent
.getBundleExtra(Intent.EXTRA_REPLACEMENT_EXTRAS);
CharSequence title = intent
.getCharSequenceExtra(Intent.EXTRA_TITLE);
int defaultTitleRes = 0;
if (title == null) {// -> false
defaultTitleRes =
com.android.internal.R.string.chooseActivity;
}
Parcelable[] pa = intent
.getParcelableArrayExtra(Intent.EXTRA_INITIAL_INTENTS);
Intent[] initialIntents = null;
if (pa != null) { // -> false
......
}
//getReferrer(): android-app://com.***.filemanager
log("getReferrer(): "+getReferrer());
mReferrerFillInIntent = new Intent()
.putExtra(Intent.EXTRA_REFERRER, getReferrer());
mChosenComponentSender = intent.getParcelableExtra(
Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER);
mRefinementIntentSender = intent.getParcelableExtra(
Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER);
//mChosenComponentSender: null
log("mChosenComponentSender: "+mChosenComponentSender);
//mRefinementIntentSender: null
log("mRefinementIntentSender: "+mRefinementIntentSender);
setSafeForwardingMode(true);
pa = intent.getParcelableArrayExtra(
Intent.EXTRA_EXCLUDE_COMPONENTS);
if (pa != null) { // -> false
......
}
pa = intent.getParcelableArrayExtra(
Intent.EXTRA_CHOOSER_TARGETS);
if (pa != null) { // -> false
......
}
/*
* prefsFile:
* /data/user/0/android/shared_prefs/chooser_pin_settings.xml
*/
mPinnedSharedPrefs = getPinnedSharedPrefs(this);
setRetainInOnStop(intent
.getBooleanExtra(EXTRA_PRIVATE_RETAIN_IN_ON_STOP, false));
/*
* 进入父类的onCreate()方法
*/
super.onCreate(savedInstanceState, target,
title, defaultTitleRes, initialIntents,
null, false);
MetricsLogger.action(this,
MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN);
mChooserShownTime = System.currentTimeMillis();
final long systemCost = mChooserShownTime - intentReceivedTime;
MetricsLogger.histogram(null,
"system_cost_for_smart_sharing", (int) systemCost);
if (DEBUG) {
//System Time Cost is 298 花费了300ms,还是慢
Log.d(TAG, "System Time Cost is " + systemCost);
}
}
下面进入父类ResolverActivity类的onCreate()方法。
protected void onCreate(Bundle savedInstanceState,
Intent intent,CharSequence title, int defaultTitleRes,
Intent[] initialIntents,List<ResolveInfo> rList,
boolean supportsAlwaysUseOption) {
setTheme(R.style.Theme_DeviceDefault_Resolver);
super.onCreate(savedInstanceState);
log("method onCreate() 7 params");
isFromScreenShot = getIntent()
.getBooleanExtra("screen_shot", false);
// Determine whether we should show that intent
// is forwarded from managed profile to owner or
// other way around.
setProfileSwitchMessageId(intent.getContentUserHint());
try {
mLaunchedFromUid = ActivityManager.getService()
.getLaunchedFromUid(getActivityToken());
} catch (RemoteException e) {
mLaunchedFromUid = -1;
}
//mLaunchedFromUid: 10044
log("mLaunchedFromUid: "+mLaunchedFromUid);
if (mLaunchedFromUid < 0
|| UserHandle.isIsolated(mLaunchedFromUid)) {// -> false
// Gulp!
finish();
return;
}
mPm = getPackageManager();
mPackageMonitor.register(this, getMainLooper(), false);
mRegistered = true;
mReferrerPackage = getReferrerPackageName();
mSupportsAlwaysUseOption = supportsAlwaysUseOption;
//com.***.filemanager
log("mReferrerPackage: "+mReferrerPackage);
//false
log("mSupportsAlwaysUseOption: "+mSupportsAlwaysUseOption);
final ActivityManager am =
(ActivityManager) getSystemService(ACTIVITY_SERVICE);
mIconDpi = am.getLauncherLargeIconDensity();
//320
log("mIconDpi: "+mIconDpi);
// Add our initial intent as the first item, regardless
// of what else has already been added.
mIntents.add(0, new Intent(intent));
mTitle = title;
mDefaultTitleResId = defaultTitleRes;
/*
* 先进入configureContentView()方法
*/
if (configureContentView(mIntents, initialIntents, rList)) {
log("configureContentView return true");
return;
}
final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
if (rdl != null) { // -> true
log("rdl: "+rdl);
rdl.setOnDismissedListener(new ResolverDrawerLayout
.OnDismissedListener() {
@Override
public void onDismissed() {
finish();
}
});
if (isVoiceInteraction()) {
rdl.setCollapsed(false);
}
mResolverDrawerLayout = rdl;
}
mProfileView = findViewById(R.id.profile_button);
if (mProfileView != null) { // -> true
log("mProfileView: "+mProfileView);
mProfileView.setOnClickListener(new View
.OnClickListener() {
@Override
public void onClick(View v) {
final DisplayResolveInfo dri = mAdapter
.getOtherProfile();
if (dri == null) {
return;
}
// Do not show the profile switch message
// anymore.
mProfileSwitchMessageId = -1;
onTargetSelected(dri, false);
finish();
}
});
bindProfileView();
}
if (isVoiceInteraction()) {
onSetupVoiceInteraction();
}
final Set<String> categories = intent.getCategories();
MetricsLogger.action(this, mAdapter.hasFilteredItem()
? MetricsProto.MetricsEvent
.ACTION_SHOW_APP_DISAMBIG_APP_FEATURED
: MetricsProto.MetricsEvent
.ACTION_SHOW_APP_DISAMBIG_NONE_FEATURED,
intent.getAction() + ":" + intent.getType() + ":"
+ (categories != null
? Arrays.toString(categories.toArray()) : ""));
mIconFactory = IconDrawableFactory.newInstance(this, true);
}
下面进入ResolverActivity类的configureContentView()方法。
/**
* Returns true if the activity is finishing and
* creation should halt
*/
public boolean configureContentView(List<Intent> payloadIntents,
Intent[] initialIntents,List<ResolveInfo> rList) {
log("method configureContentView()");
// The last argument of createAdapter is whether to do
// special handling of the last used choice to highlight
// it in the list. We need to always turn this off when
// running under voice interaction, since it results in
// a more complicated UI that the current voice interaction
// flow is not able to handle.
/*
* 这里实质调用的是子类ChooserActivity的createAdapter()方法
* 先进入这里
*/
mAdapter = createAdapter(this, payloadIntents,
initialIntents, rList,
mLaunchedFromUid,
mSupportsAlwaysUseOption && !isVoiceInteraction());
......(省略一大段代码)
}
下面进入ChooserActivity类的createAdapter()方法。
这里创建了一个ChooserListAdapter对象,它继承于ResolveListAdapter。
前者是定义在ChooserActivity类中的内部类,后者是定义在ResolverActivity类中的内部类。
@Override
public ResolveListAdapter createAdapter(Context context,
List<Intent> payloadIntents,Intent[] initialIntents,
List<ResolveInfo> rList, int launchedFromUid,
boolean filterLastUsed) {
log("method createAdapter()");
/*
* 这个构造方法中就是一些简单的赋值操作
*/
final ChooserListAdapter adapter = new ChooserListAdapter(
context, payloadIntents,initialIntents, rList,
launchedFromUid, filterLastUsed,
createListController());
return adapter;
}
下面回到ResolverActivity类的configureContentView()方法。
public boolean configureContentView(List<Intent> payloadIntents,
Intent[] initialIntents,List<ResolveInfo> rList) {
......
//这里实质调用的是子类的createAdapter()方法。
//执行完了
mAdapter = createAdapter(this, payloadIntents,
initialIntents, rList,
mLaunchedFromUid,
mSupportsAlwaysUseOption && !isVoiceInteraction());
/*
* 进入这里
* 这里实质调用的是ResolveListAdapter的rebuildList()方法。
*/
boolean rebuildCompleted = mAdapter.rebuildList();
// false
log("rebuildCompleted: "+rebuildCompleted);
if (useLayoutWithDefault()) { // -> false
log("use default layout");
mLayoutId = R.layout.resolver_list_with_default;
} else {
mLayoutId = getLayoutResource();
}
setContentView(mLayoutId);
int count = mAdapter.getUnfilteredCount();
// 0
log("count: "+count);
// We only rebuild asynchronously when we have multiple
// elements to sort. In the case where
// we're already done, we can check if we should
// auto-launch immediately.
if (rebuildCompleted) { // -> false
......
}
mAdapterView = findViewById(R.id.resolver_list);
if (count == 0 && mAdapter.mPlaceholderCount == 0) {// -> false
log("show empth view");
final TextView emptyView = findViewById(R.id.empty);
emptyView.setVisibility(View.VISIBLE);
mAdapterView.setVisibility(View.GONE);
} else {// get in
mAdapterView = findViewById(R.id.resolver_list);
//显示ListView
mAdapterView.setVisibility(View.VISIBLE);
//实质调用子类的onPrepareAdapterView()方法
onPrepareAdapterView(mAdapterView, mAdapter);
}
return false;
}
下面进入ResolveListAdapter类的rebuildList()方法。
/**
* Rebuild the list of resolvers. In some cases some parts
* will need some asynchronous work
* to complete.
*
* @return Whether or not the list building is completed.
*/
protected boolean rebuildList() {
log("method rebuildList()");
List<ResolvedComponentInfo> currentResolveList = null;
// Clear the value of mOtherProfile from previous call.
mOtherProfile = null;
mLastChosen = null;
mLastChosenPosition = -1;
mDisplayList.clear();
// null
log("mBaseResolveList: "+mBaseResolveList);
if (mBaseResolveList != null) { // -> false
currentResolveList = mUnfilteredResolveList = new ArrayList<>();
mResolverListController.addResolveListDedupe(
currentResolveList,
getTargetIntent(),
mBaseResolveList);
} else {
/*
* 重点!
* 这里查询符合Intent分享条件的app
* mResolverListController是ResolverListController对象
* 进入这个方法
*/
currentResolveList = mUnfilteredResolveList =
mResolverListController
.getResolversForIntent(shouldGetResolvedFilter(),
shouldGetActivityMetadata(),mIntents);
if (currentResolveList == null) {// -> false
processSortedList(currentResolveList);
return true;
}
List<ResolvedComponentInfo> originalList =
mResolverListController
.filterIneligibleActivities(currentResolveList,
true);
// null
log("originalList: "+originalList);
if (originalList != null) {
mUnfilteredResolveList = originalList;
}
}
......
int N;
if ((currentResolveList != null)
&& ((N = currentResolveList.size()) > 0)) {
// 4
log("N: "+N);
// We only care about fixing the unfilteredList
// if the current resolve list and
// current resolve list are currently the same.
List<ResolvedComponentInfo> originalList =
mResolverListController
.filterLowPriority(currentResolveList,
mUnfilteredResolveList == currentResolveList);
// null
log("originalList: "+originalList);
if (originalList != null) {
mUnfilteredResolveList = originalList;
}
if (currentResolveList.size() > 1) {
int placeholderCount = currentResolveList.size();
if (useLayoutWithDefault()) {// -> false
--placeholderCount;
}
// 4
log("placeholderCount: "+placeholderCount);
setPlaceholderCount(placeholderCount);
AsyncTask<List<ResolvedComponentInfo>,
Void,
List<ResolvedComponentInfo>> sortingTask =
new AsyncTask<List<ResolvedComponentInfo>,
Void,
List<ResolvedComponentInfo>>() {
@Override
protected List<ResolvedComponentInfo> doInBackground(
List<ResolvedComponentInfo>... params) {
mResolverListController.sort(params[0]);
return params[0];
}
@Override
protected void onPostExecute(
List<ResolvedComponentInfo> sortedComponents) {
processSortedList(sortedComponents);
if (mProfileView != null) {
bindProfileView();
}
notifyDataSetChanged();
}
};
log("start to execute sorting task");
//执行排序的异步任务
sortingTask.execute(currentResolveList);
/*
* 进入这里
*/
postListReadyRunnable();
return false;
} else {
processSortedList(currentResolveList);
return true;
}
} else {
processSortedList(currentResolveList);
return true;
}
}
下面进入ResolverListController类的getResolversForIntent()方法。
@VisibleForTesting
public List<ResolverActivity.ResolvedComponentInfo>
getResolversForIntent(
boolean shouldGetResolvedFilter,
boolean shouldGetActivityMetadata,
List<Intent> intents) {
log("method getResolversForIntent()");
// true
log("shouldGetResolvedFilter: "+shouldGetResolvedFilter);
// true
log("shouldGetActivityMetadata: "+shouldGetActivityMetadata);
// 1
log("intents: "+intents.size());
List<ResolverActivity.ResolvedComponentInfo> resolvedComponents = null;
for (int i = 0, N = intents.size(); i < N; i++) {
final Intent intent = intents.get(i);
/*index: 0 intent: Intent { act=android.intent.action.SEND
typ=application/vnd.android.package-archive
flg=0x8080003 clip={application/vnd.android.package-archive
U:content://com.***.filemanager.fileProvider
/external_storage/demo.apk}(has extras) }*/
log("index: "+i+" intent: "+intent);
/*
* 这里使用PackageManager查询符合Intent条件的app
*/
final List<ResolveInfo> infos = mpm.queryIntentActivities(
intent,PackageManager.MATCH_DEFAULT_ONLY
| (shouldGetResolvedFilter
? PackageManager.GET_RESOLVED_FILTER : 0)
| (shouldGetActivityMetadata
? PackageManager.GET_META_DATA : 0)
| PackageManager.MATCH_INSTANT);
// Remove any activities that are not exported.
int totalSize = infos.size();
for (int j = totalSize - 1; j >= 0 ; j--) {
ResolveInfo info = infos.get(j);
if (info.activityInfo != null
&& !info.activityInfo.exported) {
infos.remove(j);
}
}
if (infos != null) {
if (resolvedComponents == null) {
resolvedComponents = new ArrayList<>();
}
addResolveListDedupe(resolvedComponents,
intent, infos);
}
}
//当前查询出来有4个app符合
log("resolvedComponents: "+resolvedComponents);
return resolvedComponents;
}
当getResolversForIntent()这个方法执行完成以后回到rebuildList()方法。
回到rebuildList()方法后可以看见后续的流程启动了一个异步线程进行排序。
异步线程后紧接着进入ResolveListAdapter类的postListReadyRunnable()方法。
/**
* Some necessary methods for creating the list are
* initiated in onCreate and will also
* determine the layout known. We therefore can't update
* the UI inline and post to the
* handler thread to update after the current task is finished.
*/
private void postListReadyRunnable() {
log("method postListReadyRunnable()");
if (mPostListReadyRunnable == null) {
mPostListReadyRunnable = new Runnable() {
@Override
public void run() {
/*
* 这个run方法将会运行在主线程中,因为当前主线程
* 正在运行onCreate()流程,所以当onCreate()流程
* 执行完成以后才会这个runnable。
*/
log("mPostListReadyRunnable run doing......");
setTitleAndIcon();
resetAlwaysOrOnceButtonBar();
//这里的实质又是调用子类的onListRebuilt()方法
log("use son class method: onListRebuilt()");
onListRebuilt();
mPostListReadyRunnable = null;
}
};
getMainThreadHandler().post(mPostListReadyRunnable);
}
}
下面回到ResolverActivity的configureContentView()方法。
public boolean configureContentView(List<Intent> payloadIntents,
Intent[] initialIntents,
List<ResolveInfo> rList) {
log("method configureContentView()");
// The last argument of createAdapter is whether to
// do special handling of the last used choice to
// highlight it in the list. We need to always
// turn this off when running under voice interaction,
// since it results in a more complicated UI that the
// current voice interaction flow is not able to handle.
//这里实质调用的是子类的createAdapter()方法。
mAdapter = createAdapter(this, payloadIntents,
initialIntents, rList,
mLaunchedFromUid,
mSupportsAlwaysUseOption && !isVoiceInteraction());
boolean rebuildCompleted = mAdapter.rebuildList();
// false
log("rebuildCompleted: "+rebuildCompleted);
if (useLayoutWithDefault()) { // -> false
log("use default layout");
mLayoutId = R.layout.resolver_list_with_default;
} else {
mLayoutId = getLayoutResource();
}
setContentView(mLayoutId);
int count = mAdapter.getUnfilteredCount();
// 0
log("count: "+count);
// We only rebuild asynchronously when we have
// multiple elements to sort. In the case where
// we're already done, we can check if we should
// auto-launch immediately.
if (rebuildCompleted) { // -> false
......
}
mAdapterView = findViewById(R.id.resolver_list);
if (count == 0 && mAdapter.mPlaceholderCount == 0) {// -> false
log("show empth view");
final TextView emptyView = findViewById(R.id.empty);
emptyView.setVisibility(View.VISIBLE);
mAdapterView.setVisibility(View.GONE);
} else {// get in
log("get in else");
mAdapterView = findViewById(R.id.resolver_list);
//显示ListView
mAdapterView.setVisibility(View.VISIBLE);
/*
* 实质调用子类的onPrepareAdapterView()方法
*/
onPrepareAdapterView(mAdapterView, mAdapter);
}
return false;
}
下面进入ChooserActivity类的onPrepareAdapterView()方法。
@Override
public void onPrepareAdapterView(AbsListView adapterView,
ResolveListAdapter adapter) {
final ListView listView =
adapterView instanceof ListView
? (ListView) adapterView : null;
mChooserListAdapter = (ChooserListAdapter) adapter;
if (mCallerChooserTargets != null
&& mCallerChooserTargets.length > 0) { // -> false
mChooserListAdapter.addServiceResults(null,
Lists.newArrayList(mCallerChooserTargets));
}
/*
* 这里构建的才是我们真正ListView使用的Adapter,它
* 直接继承自BaseAdapter
* 其ListView的item的click响应事件是在Adapter中进行设置的
*/
mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
mChooserRowAdapter.registerDataSetObserver(
new OffsetDataSetObserver(adapterView));
adapterView.setAdapter(mChooserRowAdapter);
log("listView: "+listView);
if (listView != null) {
listView.setItemsCanFocus(true);
}
}
至此父类和子类的onCreate()方法都执行完成了。
当主线程其它流程执行完成以后就开始执行我们当设置的postListReadyRunnable()方法。
postListReadyRunnable()方法主要就是查询符合分享条件的应用还需不需要启动各自分享的service。
其核心是onListRebuilt()方法。这里将会调用子类ChooserListAdapter的onListRebuilt()方法。
至此分享的界面就显示在手机的界面上了。
点击Click事件
下面进入ChooserRowAdapter类中item的click点击事件流程。
@Override
public View getView(int position, View convertView,
ViewGroup parent) {
final RowViewHolder holder;
if (convertView == null) {
holder = createViewHolder(parent);
} else {
holder = (RowViewHolder) convertView.getTag();
}
bindViewHolder(position, holder);
return holder.row;
}
RowViewHolder createViewHolder(ViewGroup parent) {
final ViewGroup row = (ViewGroup) mLayoutInflater
.inflate(R.layout.chooser_row,parent, false);
final RowViewHolder holder = new RowViewHolder(row,
mColumnCount);
final int spec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
for (int i = 0; i < mColumnCount; i++) {
final View v = mChooserListAdapter.createView(row);
final int column = i;
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
/*
* 点击事件进入这里
*/
log("onClick: "+column);
startSelected(holder.itemIndices[column],
false, true);
}
});
v.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
log("onLongClick: "+column);
showTargetDetails(mChooserListAdapter
.resolveInfoForPosition(
holder.itemIndices[column], true));
return true;
}
});
row.addView(v);
holder.cells[i] = v;
// Force height to be a given so we don't
// have visual disruption during scaling.
LayoutParams lp = v.getLayoutParams();
v.measure(spec, spec);
if (lp == null) {
lp = new LayoutParams(LayoutParams.MATCH_PARENT,
v.getMeasuredHeight());
row.setLayoutParams(lp);
} else {
lp.height = v.getMeasuredHeight();
}
if (i != (mColumnCount - 1)) {
row.addView(new Space(ChooserActivity.this),
new LinearLayout.LayoutParams(0, 0, 1));
}
}
// Pre-measure so we can scale later.
holder.measure();
LayoutParams lp = row.getLayoutParams();
if (lp == null) {
lp = new LayoutParams(LayoutParams.MATCH_PARENT,
holder.measuredRowHeight);
row.setLayoutParams(lp);
} else {
lp.height = holder.measuredRowHeight;
}
row.setTag(holder);
return holder;
}
下面进入ChooserActivity类的startSelected()方法。
@Override
public void startSelected(int which, boolean always,
boolean filtered) {
log("method startSelected()");
final long selectionCost =
System.currentTimeMillis() - mChooserShownTime;
//调用父类的了
super.startSelected(which, always, filtered);
......
}
下面进入父类的ResolverActivity的startSelected()方法。
public void startSelected(int which, boolean always,
boolean hasIndexBeenFiltered) {
log("method startSelected()");
if (isFinishing()) {
return;
}
ResolveInfo ri = mAdapter
.resolveInfoForPosition(which, hasIndexBeenFiltered);
/*ResolveInfo{45cfa38 com.android.bluetooth/
.opp.BluetoothOppLauncherActivity m=0x608000}*/
log("ri: "+ri);
if (mResolvingHome && hasManagedProfile()
&& !supportsManagedProfiles(ri)) {
Toast.makeText(this, String.format(getResources()
.getString(com.android.internal.
R.string.activity_resolver_work_profiles_support),
ri.activityInfo.loadLabel(getPackageManager()).toString()),
Toast.LENGTH_LONG).show();
return;
}
TargetInfo target = mAdapter
.targetInfoForPosition(which, hasIndexBeenFiltered);
/*com.android.internal.app
.ResolverActivity$DisplayResolveInfo@f23ca11*/
log("target: "+target);
if (target == null) {
return;
}
/*
* 进入这里
*/
if (onTargetSelected(target, always)) {
if (always && mSupportsAlwaysUseOption) {
MetricsLogger.action(
this, MetricsProto.MetricsEvent
.ACTION_APP_DISAMBIG_ALWAYS);
} else if (mSupportsAlwaysUseOption) {
MetricsLogger.action(
this, MetricsProto.MetricsEvent
.ACTION_APP_DISAMBIG_JUST_ONCE);
} else {
MetricsLogger.action(
this, MetricsProto.MetricsEvent
.ACTION_APP_DISAMBIG_TAP);
}
MetricsLogger.action(this, mAdapter.hasFilteredItem()
? MetricsProto.MetricsEvent
.ACTION_HIDE_APP_DISAMBIG_APP_FEATURED
: MetricsProto.MetricsEvent
.ACTION_HIDE_APP_DISAMBIG_NONE_FEATURED);
finish();
}
}
下面进入ResolverActivity的onTargetSelected()方法。
protected boolean onTargetSelected(TargetInfo target,
boolean alwaysCheck) {
/* com.android.internal.app
.ResolverActivity$DisplayResolveInfo@f23ca11*/
log("target: "+target);
//false
log("alwaysCheck: "+alwaysCheck);
final ResolveInfo ri = target.getResolveInfo();
final Intent intent = target != null
? target.getResolvedIntent() : null;
// -> false
if (intent != null && (mSupportsAlwaysUseOption
|| mAdapter.hasFilteredItem())
&& mAdapter.mUnfilteredResolveList != null) {
......(省略一大段代码)
}
if (target != null) {//-> true
safelyStartActivity(target);
}
return true;
}
下面进入ResolverActivity的safelyStartActivity()方法。
public void safelyStartActivity(TargetInfo cti) {
log("method safelyStartActivity()");
// We're dispatching intents that might be coming
// from legacy apps, so don't kill ourselves.
StrictMode.disableDeathOnFileUriExposure();
try {
safelyStartActivityInternal(cti);
} finally {
StrictMode.enableDeathOnFileUriExposure();
}
}
private void safelyStartActivityInternal(TargetInfo cti) {
log("method safelyStartActivityInternal()");
/*com.android.internal.app
.ResolverActivity$DisplayResolveInfo*/
log("cti: "+cti.getClass().getName());
// If needed, show that intent is forwarded
// from managed profile to owner or other way around.
if (mProfileSwitchMessageId != -1) {
Toast.makeText(this,
getString(mProfileSwitchMessageId),
Toast.LENGTH_LONG).show();
}
// true
log("mSafeForwardingMode: " + mSafeForwardingMode);
if (!mSafeForwardingMode) {
if (cti.start(this, null)) {
onActivityStarted(cti);
}
return;
}
try {
/*
* 这里是启动启动activity的动作
*/
* @Override
* public boolean startAsCaller(Activity activity,
* Bundle options, int userId) {
* activity.startActivityAsCaller(mResolvedIntent,
* options, false, userId);
* return true;
* }
*
*/
// -> true
if (cti.startAsCaller(this, null, UserHandle.USER_NULL)) {
log("start as caller");
/*
* 这个方法是设置activity启动后的结果
* 其实质是调用子类的onActivityStarted()
*/
onActivityStarted(cti);
}
} catch (RuntimeException e) {
String launchedFromPackage;
try {
launchedFromPackage = ActivityManager
qq.getService().getLaunchedFromPackage(
getActivityToken());
} catch (RemoteException e2) {
launchedFromPackage = "??";
}
Slog.wtf(TAG, "Unable to launch as uid "
+ mLaunchedFromUid
+ " package " + launchedFromPackage
+ ", while running in "
+ ActivityThread.currentProcessName(), e);
}
}
下面进入ChooserActivity类的onActivityStarted()方法。
@Override
public void onActivityStarted(TargetInfo cti) {
log("method onActivityStarted()");
log("mChosenComponentSender: "+mChosenComponentSender);
/*
* mChosenComponentSender是
* Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER获得
*/
if (mChosenComponentSender != null) {// ->false
final ComponentName target =
cti.getResolvedComponentName();
if (target != null) {
final Intent fillIn = new Intent()
.putExtra(Intent.EXTRA_CHOSEN_COMPONENT, target);
try {
mChosenComponentSender.sendIntent(this,
Activity.RESULT_OK, fillIn, null, null);
} catch (IntentSender.SendIntentException e) {
Slog.e(TAG, "Unable to launch supplied"
+ "IntentSender to report "
+ "the chosen component: " + e);
}
}
}
}
一个完成调用系统分享的执行过程就分析完成了。
本文由 tuzhao 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2018/01/04 23:01
请问,在您的"接下来调用Intent.java中的createChooser()重载方法。"中的"log("permFlags: "+permFlags);",可以得到值吗?可以得到的话,是怎么得到的呢?