序文
この記事では、主にAndroidの意図を紹介し、Androidソースコードの観点から意図クエリマッチングプロセスを分析します。
intten introdution
Intentの中国語は「意図」を意味し、意図は非常に抽象的な概念です。したがって、Androidシステムは、意図が2つの側面で測定できることを明確に指定しています。
主な属性:アクションとデータを含む。その中でも、アクションは意図によって表されるアクション意図を表すために使用され、データはアクションによって動作するデータを表すために使用されます。
二次属性:カテゴリ、タイプ、コンポーネント、およびエクストラを含む。カテゴリはカテゴリを表し、タイプはデータのデータ型を表し、コンポーネントを使用して特定の意図の応答を指定できます(たとえば、パッケージの下のクラスクラスになる意図を指定します)。情報。
Androidシステムには、意図(明示的な意図)と隠された意図(暗黙的意図)を示す2つの主要な意図があります。
明示的な意図:このタイプの意図は、どのコンポーネントを見つけるかを明確に示します。コードでは、SetClassNameまたはSetComponentを使用してターゲットオブジェクトをロックできます。
暗黙的な意図:このタイプの意図は、どのコンポーネントを起動するコンポーネントを明確に示していませんが、アクション、データ、およびカテゴリを設定して、システムを適切なコンポーネントにします。
次に、2つのコードの例を記述して、Expllicitの意図を紹介し、無効にします。 1つ目は明示的な意図です:
private void startexplictintentwithcomponent(){intent intent = new intent();意図);} private void startexplictintentwithclassname(){intent = new Intent();ただし、ソースコードから、SetClassNameもComponentNameを使用して明示的な意図を達成することがわかりました。ソースコードは次のとおりです。
Public Intent SetClassName(String PackageName、String ClassName){mcomponent = new ComponentName(PackageName、ClassName);次に、暗黙の意図のコード例。ここでは、アクティビティを使用して、意図フィルターを例としてマークし、それを開始する意図を書きます。
<Activity android:name = "。sendintenttype"> <intent-filter> <action android:name = "justtest"/> <category android:name = "justcategory" </intent-filter> </activity>
AndroidManifest.xmlが現在適用されている場合、Intent-filterはsendintenttypeクラスに追加されます。アクティビティを開始するコードは次のとおりです。
private startimpllictintent(){new Intent()setant.addcategory( "justcativity");Intent Filterによってリストされている3つの項目は、次のように使用されます。
活動情報の管理
上記の分析から、システムの一致意図のプロセスでは、最初に現在のシステム内のすべてのアクティビティ情報を管理する必要があることがわかります。アクティビティの情報は、APKをスキャンするときにPackageManagerServiceによって収集および管理されました。関連するソースコードは次のとおりです。
//添付の態度情報n = pkg.activities.size(); .info.processname = fixprocessname(pkg.applicationinfo.processname、a.info.processname、pkg.applicationinfo.uid);};
上記のコードには、下の図に示すように、2つの重要なデータ構造があります。
コードのデータ構造と上記の図と組み合わせることで、次のことがわかります。
マキシティは、システム内のアクティビティに関連するすべての情報を保存するためのPKMのメンバー変数です。また、このデータ構造内にはMactivies変数があります。
APKから取得したすべての情報関連情報(XMLで宣言されたIntentFilterラベルを含む)は、PackageParser.Activityによって保存されます。
以前のコードは、付加性関数を呼び出して、個人情報の宣伝を完了します。付加性関数のコードは次のとおりです。
パブリックボイドアダクティブ(PackageParser.Activity A、String Type){final boolean systemApp(a.info.ApplicationInfo); int j = 0; /非システムAPKの優先度は0 Intent.setPriority(0);} addfilter(intent);}}}でなければなりません。AddFilter関数を見てみましょう。関数ソースコードは次のとおりです。
public void addfilter(F f){//すべてのintentfilter情報mfilters.add(f); type: "); if(nums == 0 && numt == 0){register_intent_filter(f.actionsitertor()、mactintofilter、" action: ");} if(numt!= 0){filter(f、f.actionsitatrator ()、mtypedactIntofilter、 "typedaction:");}}}}ここにはさらにいくつかのデータ構造があります。これらはarraymap <string、f []>に似ています。ここで、fはテンプレートパラメーターです。
近似データ構造を理解した後、Register_intent_filterの関数実装を見てみましょう。
private final int register_intent_filter(filter、iterator <string> i、arraymap <string、f [] dest、string、string、if(i == null){return 0;} int num = 0; while(i.hasnext() ){string name = ipxt();次に、別のAddFilter関数です。これは、明らかにこのAddFilterの実装を見てみましょう。
プライベートvoid addfilter(arraymap <string、f [] string name){] array = map.get(name); (名前、array)= final n = array.length(i-1] = null){i- - ;} if(i <n){array [i] = filter;} n] = filter; put(newa);}}}実際、コードはまだ非常に単純です。 Fアレイが存在しない場合は、2の容量を持つ配列を作成し、フィルターにNo. 0要素を割り当てます。
意図マッチングクエリ分析
QueryInterticivityを介したクライアントは、PackageManageerserviceにクエリ要求を開始するためのApplicationPackageManagerによる出力です。コードは次のとおりです。
@Override public List <SolutheInfo> QueryIntentActivities(Intent Intent、int Flags){return quryIntitititiationAser(intent、flags、mcontext.get userid());} / ** @hide特定のユーザーと同じList <SolutheIntertivitiesAsususer(Intent Intent、int Flags、intimeid)ifneeded(mcontext.getContentResolver())、flags、userid);} catch(remoteexception e){Throw new runtimeexception( "Package Managerは死んだ」、E);};}; }QueryIntentActivitiesの実際の実装は、PackageManagerservice.javaにあります。
パブリックリスト<ResolveInfo> QueryIntentActivities(意図、String ResolvedType、Int Flags、Int UserID){if(!susermanager.exists))collectionsemptylist()binder.getCallinguid()、userid、fals、fals " "); componentNetName comp = intent.getComponent(); if(comp == null){if(intent.getSelector()!= null){intent = intent.getSelectまたは(); comp = intent.getComponent();} } if(comp!= null){// explictの意図、対応するactiveinfo final list <resolveinfo> list = new Arrayinfo>(1); null){final resolveinfo ri = new ResolveInfo(); null){//暗黙の意図Mactivities.QueryIntent(Intent、ResolvedType、Flags、UserId);} finalPa。ckageParser.packagepkg = mpackages.get(pkgname){//パッケージを指定しますIntent Return Mactivities.QuryIntentForPackage(Intent、ResolvedType、Flags、Pkg.activities、userId);明示的な意図の実装は比較的単純であることがわかります。 QueryIntentメソッドと呼ばれる暗黙の意図。
Public List <SolutheInfo> QueryIntent(Intent Intent、String ResolvedType、int userid){if(!susermanager.erid))return super.queryintent(flags&packagemanager .match_default_only; )!= 0、userid);}IntentResolver.javaのQueryIntentメソッドの追跡を続け、ソースコードは次のとおりです。
パブリックリスト<r> QueryIntent(Intent Intent、String ResolvedType、Boolean Defaultonly、Interic){string scheme = intent.getScheme();一致する操作f [] firsttypecut = null; slashpos = ResolvedType.indexof( '/'); .length()!= slashpos+2 ||。タイプマッチ= mtypetofilter.get = mwildyp eTofilter.get;} ;} //任意の *タイプは常に適用されますが、これを行う必要があります。 !! )データuri、つまり、そのスキームに一致するすべてのファイルを収集する必要があります。 ;} // INTERTがMIMEタイプまたは// URIのいずれかを指定していない場合、Matched empty //データのみを探しますnull){firsttypecut = mactiontofilter.get(intent.get.get()); secondTypecut! 、ThirdTypecut、ファイナリスト、userid);} if(schemecut!= null){builtretholvelist(intent、cate gories、debug、defoltonly、resolvedtype、schemecut、finalist、userid);} sortresults(ファイナリスト);特定のクエリマッチングプロセスは、BuildResolvelist関数によって完了します。クエリの一致する実装のためのコードを投稿しません。