Vorwort
In diesem Artikel wird hauptsächlich Android -Absicht eingeführt und analysiert den Abfrageabfrage -Übereinstimmungsprozess aus der Perspektive des Android -Quellcode.
Intten EINLEITUNG
Intent's Chinese bedeutet "Absicht", und die Absicht ist ein sehr abstraktes Konzept. Daher gibt das Android -System eindeutig an, dass eine Absicht an zwei Aspekten gemessen werden kann.
Hauptattribute: einschließlich Aktion und Daten. Unter ihnen wird die Aktion verwendet, um die von der Absicht ausgedrückte Aktionsabsicht darzustellen, und Daten werden verwendet, um die durch die Aktion betriebenen Daten darzustellen.
Sekundärattribute: einschließlich Kategorie, Typ, Komponente und Extras. Die Kategorie repräsentiert die Kategorie, der Typ repräsentiert den Datentyp der Daten, und Komponenten können verwendet werden Information.
Es gibt zwei Haupttypen der Absicht im Android -System, die die Absicht (explizite Absicht) und versteckte Absicht (implizite Absicht) zeigen.
Explizite Absicht: Diese Art von Absicht zeigt deutlich an, welche Komponente zu finden sind. Im Code können Sie das Zielobjekt über setClassName oder setComponent sperren.
Implizite Absicht: Diese Art von Absicht zeigt nicht klar an, welche Komponente zu starten ist, sondern legt die Aktion, die Daten und die Kategorie fest, um den Systembildschirm zur entsprechenden Komponente zu machen.
Schreiben Sie als nächstes zwei Code -Beispiele, um die Explitic -Absicht einzuführen und die Einführung zu implementieren. Die erste ist explizite Absicht:
Private void startExPlictentIntewithComponent () {Intent Intent = new Intent (); Intent);} private void startExPlictentIntewithClassName () {Intent Intent = New Intent ();Aus dem Quellcode stellte ich jedoch fest, dass SetClassName auch den Komponentnamen verwendet hat, um eine explizite Absicht zu erreichen. Der Quellcode lautet wie folgt:
Public Intent setClassName (String -Packagename, String ClassName) {mcomponent = new componentName (packagename, className);Dann ein Codebeispiel der impliziten Absicht. Hier benutze ich eine Aktivität, um einen Absichtsfilter als Beispiel zu markieren und dann eine Absicht zu schreiben, ihn zu starten.
<Activity Android: name = ". SendIntentType"> <Intent-Filter> <Action Android: name = "JustTest"/> <category Android: name = "JustCategory" </intent-f ilter> </Aktivität>
In AndroidManifest.xml wird der Intent-Filter zur SendIntype-Klasse hinzugefügt. Der Code, der die Aktivität startet, lautet wie folgt:
Private void startImplLlictintent () {Intent Intent = New Intent ();Bei der Übereinstimmung mit dem impliziten Absichtsprozess werden die drei von Intent Filter aufgeführten Elemente als Referenzstandard verwendet.
Management von Aktivitätsinformationen
Aus der obigen Analyse ist ersichtlich, dass Sie im Prozess der Systemabsichten zunächst alle Aktivitätsinformationen im aktuellen System verwalten müssen. Die Informationen der Aktivität wurden von PackageManagerService beim Scannen von APK gesammelt und verwaltet. Der zugehörige Quellcode lautet wie folgt:
// Die beigefügten Stempelinformationen n = pkg.aktivitäten.size (); r = null; A .info.ProcessName = FixProcessName (pkg.applicationInfo.Processname, A.info.Processname, pkg.applicationInfo.uid);
Im obigen Code gibt es zwei wichtige Datenstrukturen, wie in der folgenden Abbildung gezeigt.
In Kombination mit der Datenstruktur des Codes und der obigen Abbildung ist ersichtlich:
Macitivitys ist der Aktivitätstyp. In dieser Datenstruktur gibt es auch eine Variable der MACTIVIES.
Alle von der APK (einschließlich des in XML deklarierte IntentFilter -Etikett deklarierten IntentFilter -Etiketten) werden von packageParser.aktivität gespeichert.
Der vorherige Code ruft die AddActivity -Funktion auf, um die Werbung für private Informationen zu vervollständigen. Der Code der AddActivity -Funktion lautet wie folgt:
Public final void addActivity (packageParser.aktivität A, String -Typ) {endgültig boolean systemApp = issystemApp (A.info.ApplicationInfo); Int j = 0; / Nicht -System -APK -Priorität muss 0 intent sein.Schauen wir uns die AddFilter -Funktion an. Der Funktionsquellcode lautet wie folgt:
Public void addFilter (f f) {// mFilters, um alle IntentFilter -Informationen zu speichern. Typ: "); if (nums == 0 && numt == 0) {register_intent_filter (f.actionStertor (), mactintofilter," Aktion: ");} if (numt! = 0) {filter (f, f.actionStatriator (), MtypedActintofilter, "TypedAction:");}}}}Hier gibt es einige weitere Datenstrukturen.
Nachdem wir die ungefähre Datenstruktur verstanden haben, schauen wir uns die Funktionsimplementierung von Register_intent_filter an:
Private endgültige 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 ();Dann ist es eine weitere Addfilter -Funktion, die offensichtlich eine Funktionsbelastung ist.
Private endgültige void addfilter (ArrayMap <String, f [] map, String -Name, Filter) {f [] array = map.get (Name); (Name, Array); if (i <n) {Array [i] = filter;} else {f [] newa = newsray ((n*3)/2); n] = filter; map.put (Name, Newa);}}}Tatsächlich ist der Code immer noch sehr einfach. Wenn das F -Array nicht vorhanden ist, erstellen Sie ein Array mit einer Kapazität von 2 und weisen Sie dem Filter das Element Nr. 0 zu.
Absichtsanalyseanalyse
Der Client über die Funktion "QueryIntentActivities" von ApplicationPackAGEMAGERAGE, um eine Abfrageanforderung an den PackageManageerService zu initiieren.
@Override Public List <ResolvEInfo> queryIntentActivities (Absicht, int Flags) {return QuryIntititiesAser (Intent, Flags, mcontext.get userId ());} / ** @Hide wie oben, aber für einen bestimmten Benutzer* / @Override Public public public public LIST <SreparationInfo> queryIntentActivitiesAsuser (Intent Intent, int Flags, IntimED) ifNeed (mcontext.getContentResolver ()), Flags, userID);} catch (remoteexception e) {Wurf neu runtimexception ("Package Manager ist gestorben";};};};};};}};};}} }Es ist zu erkennen, dass die tatsächliche Implementierung von QueryIntentActivities in PackageManagerService.java liegt.
Public list <SresolveInfo> queryIntentActivities (Absicht, String ResoledType, int Flags, int userId) {if (! Susermanager.exists) collections.EmptyList (); "); ComponentNetName comp = intent.getComponent (); if (comp == null) {if (intent.getSelector ()! } if (comp! NULL) {Final ResolveInfo ri = new ResolvEInfo (); null) {// implizite Absicht return macctivities.Queryintent (Intent, Auflösungstyp, Flags, userId);} Finale Pa. Name der Intent Return Mactivities.QuryintentForpackage (Absicht, Auflösungstyp, Flaggen, pkg.aktivitäten, userID);Es ist ersichtlich, dass die Umsetzung explizite Absicht relativ einfach ist. Implizite Absicht genannt die QueryIntent -Methode.
Public list <SresolveInfo> queryIntent (Intent Intent, String ResoledType, int Flags, int userId) {if (! SuserManager.erid)) NULL return; )! = 0, userId);}Verfolgen Sie weiterhin die QueryIntent -Methode von InsNresolver.java, der Quellcode lautet wie folgt:
Öffentliche Liste <R> QueryIntent (Intent Intent, String ResoledType, boolean defaultonly, intimerisch) {String Scheme = Intent.getScheme (); Runden der passenden Operation f [] Firstypecut = NULL; SlashPos = ResoledType.Indexof ('/'); .Length ()! = Slashpos+2 || Typ -Übereinstimmungen. } // alle */ *Typen gelten immer, aber wir müssen dies nur tun, wenn der Typ nicht Almedy war */ *. ) !! ); ;} // Wenn das Intert keine Daten angibt - entweder ein MIME -Typ oder // ein URI - werden wir nur nach leerem Anpassungsdaten suchen. Null) {firstTypecut = mactionTofilter.get (intent.get.get ()); SecondTypecut! , ThirdTyPecut, Finalist, UserId);} if (Schemecut!Der spezifische Abfrageanpassungsvorgang wird durch die BuildResolvelist -Funktion abgeschlossen. Ich veröffentliche den Code nicht für die passende Implementierung der Abfrage.