머리말
이 기사는 주로 Android 의도를 소개하고 Android 소스 코드의 관점에서 의도 쿼리 매칭 프로세스를 분석합니다.
Intten 소개
의도의 중국인은 "의도"를 의미하며 의도는 매우 추상적 인 개념입니다. 따라서 Android 시스템은 의도를 두 가지 측면으로 측정 할 수 있음을 명확하게 지정합니다.
주요 속성 : 작업 및 데이터 포함. 그 중에서도 동작은 의도로 표현 된 조치 의도를 나타내는 데 사용되며 데이터는 동작에 의해 작동하는 데이터를 나타내는 데 사용됩니다.
보조 속성 : 카테고리, 유형, 구성 요소 및 엑스트라 포함. 범주는 카테고리를 나타내고, 유형은 데이터 유형을 나타내며, 구성 요소는 특정 의도의 응답을 지정하는 데 사용될 수 있으며 (예 : 패키지 아래에 클래스 클래스가되기위한 의도를 지정 함) 엑스트라는 기타를 운반하는 데 사용됩니다. 정보.
안드로이드 시스템에는 두 가지 주요 유형의 의도가 있으며, 이는 의도 (명백한 의도)와 숨겨진 의도 (암시 적 의도)를 보여줍니다.
명시 적 의도 :이 유형의 의도는 어떤 구성 요소를 찾을 지 명확하게 나타냅니다. 코드에서 SetClassName 또는 SetComponent를 통해 대상 객체를 잠글 수 있습니다.
암시 적 의도 :이 유형의 의도는 시작할 구성 요소를 명확하게 나타내지 않지만 시스템 화면을 적절한 구성 요소로 만들기 위해 작업, 데이터 및 범주를 설정합니다.
다음으로, 설명 의도를 소개하고 inent를 암시하기 위해 두 가지 코드 예제를 작성하십시오. 첫 번째는 명백한 의도입니다.
private void startExplicitIntentWithComponent () {의도 의도 = new intent (); "com.example.photocrop", "com.ex"ample.photocrop.mainactivity "; startActivity (startActivity); 의도);} private void startExplicitIntentWithClassName () {의도의 의도 ();그러나 소스 코드에서 SetClassName은 ComponentName을 사용하여 명시 적 의도를 달성 한 것으로 나타났습니다. 소스 코드는 다음과 같습니다.
public intent setclassName (String packagename, String className) {mcomponent = new ComponentName (Packagename, ClassName);그런 다음 암시 의도의 코드 예제. 여기서는 활동을 사용하여 의도 필터를 예제로 표시 한 다음 시작하려는 의도를 작성합니다.
<Activity Android : name = ". sendIntentType"> <intent-filter> <action android : name = "JustTest"/> <카테고리 Android : "JustCategory"</intent-f ilter> </activity>
AndroidManifest.xml에서 현재 적용되는 경우 의도 필터는 SendintentType 클래스에 추가됩니다. 활동을 시작하는 코드는 다음과 같습니다.
private void startimpllictintent () {의도의 의도 ();묵시 의도 프로세스와 일치하는 과정에서 의도 필터로 나열된 세 가지 항목은 기준 표준으로 사용됩니다.
활동 정보 관리
위의 분석에서 시스템 일치 의도 프로세스에서 먼저 현재 시스템의 모든 활동 정보를 관리해야한다는 것을 알 수 있습니다. Activity의 정보는 APK를 스캔 할 때 Packagemanagerservice에 의해 수집 및 관리되었습니다. 관련 소스 코드는 다음과 같습니다.
// 첨부 된 다락방 정보 N = pkg.activities.size (); a .info.processName = fixProcessName (pkg.applicationInfo.processName, a.info.processName, pkg.applicationInfo.uid);
위의 코드에는 아래 그림과 같이 두 가지 중요한 데이터 구조가 있습니다.
코드의 데이터 구조와 위의 그림과 결합하여 볼 수 있습니다.
CAMITIVES는 ActivityIntentResolver 유형입니다. 이 데이터 구조에는 mactivies 변수가 있습니다.
APK에서 얻은 모든 정보 관련 정보 (XML로 선언 된 intentFilter 레이블 포함)는 PackageParser.Activity에 의해 저장됩니다.
이전 코드는 개인 정보의 홍보를 완료하기 위해 AddActivity 기능을 호출합니다. AddActivity 함수의 코드는 다음과 같습니다.
공개 최종 void AddActivity (PackageParser.Activity A, String 유형) {최종 부울 SystemApp = issystemApp (a.info.applicationInfo); int j = 0; / 비 시스템 APK의 우선 순위는 0 의도가되어야합니다. 세트 프라이셔티 (0);} AddFilter (의도);}}AddFilter 기능을 살펴 보겠습니다. 함수 소스 코드는 다음과 같습니다.
공개 AddFilter (f f) {// 모든 의도 정보를 저장하기위한 mfilters.add (f); 유형 : "); if (nums == 0 && numt == 0) {register_intent_filter (f.ActionSiterTor (), mactintofilter,"action : ");} if (numt! = 0) {filter (f, f.AccionSitatrator (), mtypedactintofilter, "typedaction :");}}}}여기에는 몇 가지 더 많은 데이터 구조가 있습니다. 여기서는 F가 템플릿 매개 변수입니다.
대략적인 데이터 구조를 이해 한 후 register_intent_filter의 기능 구현을 살펴 보겠습니다.
Private Final int Register_Intent_Filter (필터, 반복자 <string> i, ArrayMap <String, f [] dest, String, string, if (i == null) {return 0;} int num = 0; while (i.hasnext () ) {string name = ipxt ();그런 다음 또 다른 AddFilter 기능입니다.
개인 최종 void addfilter (arraymap <string, f [] map, 문자열 이름, 필터) {f [] array = map.get (array == null); (이름, 배열) [0] = else {int i = n; if (i <n) {array [i] = filter;} else {f [] newsray ((n*3)/2); n] = 필터; map.put (name, newa);}}}실제로 코드는 여전히 F 배열이 존재하면 용량이 판단되고 충분하지 않으면 위치 삽입을 찾으십시오. F 배열이 존재하지 않으면 용량이 2 인 배열을 작성하고 No. 0 요소를 필터에 할당하십시오.
의도 일치하는 쿼리 분석
QueryIntentActivities를 통한 클라이언트는 ApplicationPackagemanager의 기능 출력을 통해 PackagemanageErservice에 대한 쿼리 요청을 시작합니다. 코드는 다음과 같습니다.
@override public list <ReSolveInfo> QueryIntentActivities (의도 의도, int 플래그) {return quryIntititiitiesAser (의도, 플래그, mcOntext.get userId ());} / ** @Hide는 위와 동일하지만 특정 사용자* / @OverRidide public List <ResolveInfo> QueryIntentActivitiesAsusser (의도 의도, int 플래그, intimeid) ifneeded (mcontext.getContentResolver ()), 플래그, userID);} catch (remoteexception e) {새로운 runtimeexception ( "패키지 관리자가 죽었다");}. }QueryIntentActivities의 실제 구현은 PackagemanagerService.java에 있습니다.
공개 목록 <resolveInfo> QueryIntentActivities (의도의 의도, 문자열 resolvedType, int flags, int userId) {if (! susermanager.exists)) collections.empylist (); "; } if (comp! = null) {// 명시 적 의도, 해당 활동을 직접 얻습니다. 최종 목록 = new arrayinfo> (1); null) {최종 ResolveInfo ri = ri.activityInfo = add (}; null) {// 암시 적 의도 return mactivities.queryIntent (의도, resolvedType, flags, userId);} 최종 pa. ckageparser.package pkg = mpackages.get (pkgname) {// 패키지 의도의 이름 return mactivities.quryIntentForPackage (의도, ResolvedType, pkg.activities, userId);명시 적 의도의 구현은 상대적으로 간단하다는 것을 알 수 있습니다. QueryIntent 메소드라고 불리는 암시 적 의도.
공개 목록 <resolveInfo> QueryEntent (의도의 의도, String resolvedType, int userId) {if (! susermanager.erid)) return null; )! 0, userId);}intentresolver.java의 QueryEntent 메소드를 계속 추적하면 소스 코드는 다음과 같습니다.
공개 목록 <R> QueryEntent (의도의 의도, 문자열 ResolvedType, 부울 기본 이식, Intimeric) {string scheme = gettscheme (); 일치하는 작업 F [] FirstTypecut = null; slashpos = resolvedtype.indexof ( '/') {최종 문자열 baseType = resrinetype = lvedtype.substring (0, slashpos); .length ()! = 슬래시+2 || 첫 번째는 mtypetofilter.get (resolvedType); ;} // 모든 */ *유형은 항상이 작업을 수행하면됩니다. ) !! ); 데이터 URI, 우리는 그 구성표와 일치하는 모든 파일을 수집하고자한다. ;} // Intert가 데이터를 지정하지 않으면 -MIME 유형 또는 // URI- If (resolute == NULL && intentAction ()! = NULL) {FirstTyPecut = mactionTofilter.get (intent.get.get ()); SecondTypecut! = null) {buildResolvelist (의도, 카테고리, 디버그, 기본 구성, 체계, 체계, s econdtypecut, finallist, userId);} if (ThirdTypecut! = null) {buildResolvelist (의도, 카테고리, 디버그, 디버전, 재판매, Scheme. , ThirdTypecut, Finalist, userId);} if (schemecut! = null) {builtresolvelist (의도, Cate Gories, Debug, DefaultOnly, ResolvedType, Schemecut, Finalist);} Sortresults (Finalist);특정 쿼리 매칭 프로세스는 BuildResolvelist 함수에 의해 완료됩니다. 쿼리의 일치 구현에 대한 코드를 게시하지 않습니다.