Avant-propos
Cet article présente principalement l'intention d'Android et analyse le processus de correspondance de la requête d'intention du point de vue du code source Android.
INTRODUCTION INTTEN
L'intention chinoise signifie «intention», et l'intention est un concept très abstrait. Par conséquent, le système Android spécifie clairement qu'une intention peut être mesurée par deux aspects.
Attributs principaux: y compris l'action et les données. Parmi eux, l'action est utilisée pour représenter l'intention d'action exprimée par l'intention, et les données sont utilisées pour représenter les données exploitées par l'action.
Attributs secondaires: y compris la catégorie, le type, les composants et les extras. La catégorie représente la catégorie, le type représente le type de données de données et les composants peuvent être utilisés pour spécifier la réponse d'une intention spécifique (par exemple, en spécifiant l'intention d'être une classe dans un package), et des extras sont utilisés pour transporter d'autres information.
Il existe deux principaux types d'intention dans le système Android, qui montre l'intention (intention explicite) et l'intention cachée (intention implicite).
Intention explicite: Ce type d'intention indique clairement quel composant trouver. Dans le code, vous pouvez verrouiller l'objet cible via setClassName ou setComponent.
Intention implicite: Ce type d'intention n'indique pas clairement le composant à démarrer, mais définit l'action, les données et la catégorie pour faire de l'écran système le composant approprié.
Ensuite, écrivez deux exemples de code pour introduire l'intention d'expllicite et implicitement INENT. La première est une intention explicite:
Private void startExplicitIntentWithComponent () {Intent Intent = new Intent (); ComponentName Component = new ComponentName ("com.example.photocrop", "com.ex" Intention);} private void startExplicitIntAntwithClassName () {Intent Intent = new Intent ();Cependant, à partir du code source, j'ai constaté que SetClassName a également utilisé ComponentName pour atteindre l'intention explicite. Le code source est le suivant:
Intention publique setClassName (String PackageName, String className) {mComponent = new ComponentName (packageName, className);Ensuite, un exemple de code de l'intention implicite. Ici, j'utilise une activité pour marquer un filtre d'intention à titre d'exemple, puis j'écris une intention de le démarrer.
<Activité Android: name = ". SendIntentType"> <intention-filter> <Action Android: name = "JustTest" /> <catégorie Android: name = "JustCategory" </ntnt-f ilter> </ Activity>
Dans Androidmanifest.xml actuellement appliqué, le filtre d'intention est ajouté à la classe SendIntentType. Le code qui démarre l'activité est le suivant:
Private void startIMPLLICTIntent () {Intent Intent = new Intent ();Dans le processus de correspondance du processus d'intention IMPLICT, les trois éléments répertoriés par le filtre d'intention seront utilisés comme norme de référence.
Gestion des informations d'activité
D'après l'analyse ci-dessus, on peut voir que dans le processus d'intention de correspondance du système, vous devez d'abord gérer toutes les informations d'activité dans le système actuel. Les informations de l'activité ont été collectées et gérées par PackageManagerservice lors de la numérisation de l'APK. Le code source connexe est le suivant:
// traite les informations atturales jointes n = pkg.activities.size (); r = null; A .info.processName = fixProcessName (pkg.applicationinfo.processName, a.info.processName, pkg.applicationinfo.uid);
Dans le code ci-dessus, il existe deux structures de données importantes, comme le montre la figure ci-dessous.
Combiné avec la structure de données du code et de la figure ci-dessus, on peut voir:
Les macitivités sont le type d'activité Imptoffable. Il existe également une variable MACTIVIES à l'intérieur de cette structure de données.
Toutes les informations liées aux informations obtenues à partir de l'APK (y compris l'étiquette IntentFilter déclarée dans XML) sont enregistrées par PackageParser.Activity.
Le code précédent appelle la fonction AddActivity pour compléter la publicité des informations privées. Le code de la fonction AddActivity est le suivant:
Public Void AddActivity (packageParser.Activité a, type de chaîne) {final boolean systemApp = issystemApp (a.info.ApplicationInfo); Int j = 0; j <ni; j ++) {packageParSer.Activity / La priorité de l'APK non système doit être 0 intention.setPriority (0);} addFilter (intention);}}Jetons un coup d'œil à la fonction addFilter. Le code source de la fonction est le suivant:
Public void addFilter (f f) {// mfilters pour enregistrer toutes les informations 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:");}}}}Il y a plusieurs structures de données supplémentaires ici.
Après avoir compris la structure de données approximative, jetons un coup d'œil à l'implémentation de la fonction de registre_intent_filter:
Private finm regrins_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 ();Ensuite, il s'agit d'une autre fonction AddFilter, qui est évidemment une charge lourde de fonction.
Final Void addFilter (arraymap <String, f [] map, nom de chaîne, filtre) {f [] array = map.get (name); (nom, array); if (i <n) {array [i] = filtre;} else {f [] newa = newsray ((n * 3) / 2); n] = filtre; map.put (nom, newa);}}}En fait, le code est toujours très simple. Si le tableau F n'existe pas, créez un tableau avec une capacité de 2 et attribuez l'élément n ° 0 au filtre.
Analyse des requêtes correspondant à l'intention
Le client par le biais de la fonction de requête IntentAntivities par ApplicationPackageManager pour lancer une demande de requête au PackageManageService.
@Override Public List <ResolveInfo> QueryIntentActivities (INTING INTING, INT FLAGS) {return QuryIntititiesAser (Intention, Flags, mContext.get userId ());} / ** @Hide Idem que ci-dessus mais pour un utilisateur spécifique * / @Override public List <résolveinfo> queryIntentAntivitiesAsUser (intention intention, int draps, intimeid) ifneeded (mContext.getContentResolver ()), Flags, userId);} catch (RemoteException e) {Throw RuntimeException ("Package Manager est décédé", e);}; }On peut voir que la véritable implémentation de QueryIntentAtivities se trouve dans PackageManagerservice.java.
Liste publique <ResolveInfo> QueryIntentActivities (INTERNET INTENCE, String ResolvedType, Int Flags, int userId) {if (! SraserManager.Exists)) Collection.EmptyList (); "); ComponentNetName comp = Intent.getComponent (); if (comp == null) {if (Intent.getSelector ()! = Null) {Intent = Intent.getSelect ou (); comp = Intent.getComponent ();} } if (comp! = null) {// Explicit's Intention, obtenez directement la liste finale d'activité correspondante <ResolveInfo> list = new ArrayInfo> (1); Null) {Final ResolveInfo Ri = new ResolveInfo (); null) {// Implicit Intent return mactivities.QueryIntent (intention, résolvedType, Flags, Userid);} PA. Nom de l'intention de retour mactivities.QuryIntentForpackage (intention, résolveType, Flags, pkg.activities, userId);On peut voir que la mise en œuvre de l'intention explicite est relativement simple. Intention implicite appelée la méthode de questionnement de la question.
Liste publique <ResolveInfo> QueryIntent (INTERNE INTENCE, String ResolvedType, Int Flags, int userId) {if (! SraserManager.Erid)) Null; )!Continuez à suivre la méthode de questionnement de question d'intentionResolver.java, le code source est le suivant:
Public List <R> QueryIntent (Intention Intention, String ResolvedType, Boolean DefaultOnly, Intimeric) {String Scheme = Intent.getscheme (); Rounds de l'opération de correspondance f [] FirstTypecut = null; f [] SeaCondTypecut = null; f [] ThingThTypecut = null; Slashpos = résolvedType.Indexof ('/'); .length ()! = slashpos + 2 || Type Match. ;} // Les types * / * s'appliquent toujours, mais nous devons le faire // si le type n'était pas almedy * / *. ) !! ); ;} // Si l'INTERT ne spécifie pas de données - soit un type MIME ou // URI - alors nous rechercherons uniquement des données vides //. Null) {FirstTypecut = mActionTofilter.get (Intent.get.get ()); SecondTypecut! , ThirdTypecut, finaliste, utilisateur);} if (schemecut! = Null) {builtreSolvelist (intention, cate gories, debug, par défaut, résolveType, schéma, schemecut, finaliste, utilisateur);} SORTRESULTS (finaliste);Le processus de correspondance de requête spécifique est rempli par la fonction BuildResolvelist. Je ne publie pas le code pour l'implémentation correspondante de la requête.