wake-up-neo.net

Android kompilierte Ressourcen - resources.arsc

Ich versuche herauszufinden, was es bedeutet, "Ressourcen zusammenzustellen".

Was ich getan habe, um dieses Problem zu verstehen:

Ich habe viele Artikel zu diesem Thema gelesen, aber keine einfache Antwort gefunden .. Das beste, was ich gelesen habe, war Folgendes: Wie funktioniert die Zuordnung zwischen Android-Ressourcen und Ressourcen-ID? .

Wie ich es verstehe:

Nach meinem Verständnis erstellen wir unser Projekt entweder über ANT (Eclipse) oder Gradle (AS) . Wir verwenden ein Werkzeug namens aapt - Android Asset Packaging Tool, mit dem: Eindeutige IDs generiert werden für jede unserer Ressourcen, z. B. unsere Layouts, unsere Stile und mehr, und speichern Sie sie in einer Nachschlagetabelle. Dann bleibt diese Lookup-Tabelle bestehen, indem zwei Dateien generiert werden:

  1. Es generiert die R.Java-Datei mit diesen eindeutigen IDs, sodass wir während des Kompilierens unsere Ressourcen aus unserem Java-Code verwenden können. 
  2. Es generiert die Datei resources.arsc, die sich in der Ressource * .ap_-Datei befindet. Diese Ressource.arsc-Datei wird später vom apktool in die apk gepackt.
    Dieses arsc-Dateiformat ist ein Format, das vom Gerät zur Laufzeit leicht zugeordnet und analysiert werden kann.

Ein Beispiel:

Um es einfach zu machen: Sagen wir, ich habe folgendes in meiner activity_main.xml:

    <TextView Android:id="@+id/my_textView"
        Android:text="@string/hello_world" 
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" />

Und ich nenne es von onCreate aus mit:

findViewById(R.id.my_textView)

In meiner R.Java-Datei sehe ich:

public static final int my_textView=0x7f08003f;

Mit: aapt dump resources auf der generierten apk Ich sehe, dass es zwei Zeilen mit my_textView enthält: Ec resource 0x7f08003f com.example.lizi.liortest2: id/my_textView: flags = 0x00000000 .liortest2: id/my_textView: t = 0x12 d = 0x00000000 (s = 0x0008 r = 0x00)

Was ich nicht verstehe:

Ich hätte gedacht, dass diese resources.arsc-Datei nicht nur die Ressourcen-ID enthält, sondern auch alle Eigenschaften, die ich für die Ansicht definiert habe, beispielsweise Android: layout_width = "wrap_content".

Also jetzt zur Laufzeit, wenn die VM versucht, findViewById(R.id.my_textView) auszuführen. Woher weiß sie, welche Ansicht/Eigenschaften sie erhalten sollen?

Ich kann einfach nicht verstehen, wie es funktioniert ... Sollte diese Nachschlagetabelle nicht auch die Eigenschaftsdaten enthalten? Und wie lautet diese 0x7f08003f-Nummer? (Sollte es einen Wert darstellen, der später dem physischen Speicher zugeordnet wird, in dem das Objekt gespeichert wird?)

23
ZiviMagic

TL; DR: Mit Hilfe von Android Compiler (aapt) XML-Knoten werden in Klassen Java und die entsprechenden Attribute in numerische IDs übersetzt. Android Runtime arbeitet mit diesen IDs, um Klassen zu instanziieren, um die Ansichten zu erstellen

TL; R

Führen Sie diesen Befehl aus, um die binäre XML zu sichern
_aapt d xmltree apk_file_name res/layout/activity_main.xml_ ( aapt befindet sich in Android-sdk-dir/build-tools/23.0.2/aapt.exe )

Dadurch werden die XML-Knoten (z. B. LinearLayout, RelativeLayout usw.) mit ihren Attributen (z. B. _Android:layout_width, Android:layout_height_) und ihren Werten angezeigt. Beachten Sie, dass die Konstanten _match_parent_ (Zahlenwert _0xffffffff_ oder _-1_) oder _wrap_content_ (Zahlenwert _0xfffffffe_ oder _-2_) dort zu sehen sind .

Tatsächlich können Sie diesen Befehl für alle anderen XML-Dateien in der apk verwenden, z. _AndroidManifest.xml or layout files_

Die apk-Datei ist nur ein Zip-Archiv, das alle Java Klassendateien (_classes.dex_), alle kompilierten Ressourcendateien und eine Datei mit dem Namen _resources.arsc_ enthält. Diese _resource.arsc_ -Datei enthält alle Metainformationen zu den Ressourcen. Einige davon sind ...

  • die XML-Knoten (z. B. LinearLayout, RelativeLayout usw.),
  • die Attribute (z. B. _Android:layout_width_),
  • die Ressource id 's.

Die Ressourcen id beziehen sich auf die realen Ressourcen in der apk-Datei. Die Attribute werden zur Laufzeit in einen Wert aufgelöst. Der Auflösungsprozess ist für jede Umleitung (_@dimen/..._ im Gegensatz zu _4dp_ oder _@color/..._ im Gegensatz zu _"#FFaabbcc"_) intelligent und gibt einen verwendbaren Wert (a dimen Wert wird anders aufgelöst als ein color Wert).

Was ist eine kompilierte XML-Datei : Eine kompilierte XML-Datei ist genau dieselbe XML-Datei, deren Ressourcenverweise in die entsprechenden ids geändert wurden. Beispielsweise wird eine Referenz _@string/ok_ durch _0x7f000001_ ersetzt. Darüber hinaus werden die Attribute aus dem Namensraum Android in ihre jeweiligen ganzzahligen Werte geändert (z. B. _wrap_content_ wird in _0xfffffffe_ oder _-2_ geändert).

Wie Android Ressourcen zur Laufzeit auflöst : Die Methode inflater.inflate() analysiert eine kompilierte XML-Datei und erstellt eine Ansichtshierarchie durch Instanziieren der XML-Knoten. Jeder der XML-Knoten wird durch eine Klasse Java instanziiert (z. B. LinearLayout.Java, RelativeLayout.Java). Zur Instanziierung analysiert der Inflater die kompilierte XML-Datei, sammelt alle Attribute eines Knotens und erstellt eine gepackte Struktur vom Typ AttributeSet . Dieses AttributeSet wird an den Klassenkonstruktor übergeben. Der Klassenkonstruktor hat die Verantwortung, den AttributeSet zu durchlaufen und jeden der Attributwerte aufzulösen.

Beispiel: Bei einem Layout mit RelativeLayout packt das inflater _layout_width_ und _layout_height_ in ein AttributeSet und übergibt es an das Konstruktor RelativeLayout (Kontextkontext, AttributeSet-Attribute, int defStyleAttr, int defStyleRes) . In diesem Fall werden einige der Attribute und ihre Werte von RelativeLayout.initFromAttributes() und der Rest von den übergeordneten ViewGroup.initFromAttributes() aufgelöst.

_Android:id_ einer Ansicht ist nur ein weiteres Attribut. Der Inflater speichert die ID jeder Ansicht, indem er setId(id) in dieser Ansicht nach der Instanziierung aufruft

Nun zur Beantwortung Ihrer Frage _R.id_ ist ein Java-Array und _my_textview_ ist eine Ganzzahl in diesem Array . Das id der Sicht _my_textview_ ist diese ganze Zahl (beginnt mit 0x7f). Die Methode findViewById() führt eine Tiefensuche in dieser Ansichtshierarchie durch, um die jeweilige Ansicht zu finden.

Hoffe das hilft. Das link , das Sie in Ihrer Frage angegeben haben, beantwortet bereits, wie die IDs von aapt generiert werden.

Es ist ein wunderbares System zum Verwalten von Ressourcen für Geräte mit verschiedenen Variationsdimensionen. Darüber hinaus ist die Implementierung sehr schnell !! Auf dieser Grundlage können Funktionen höherer Ebenen implementiert werden (z. B. Runtime Resource Overlay ).

27
pellucide

LayoutInflater Aufblasen der Ansicht mithilfe von XML-Zeichenfolgen. XML-Zeichenfolgen, die wie in Ihrer Frage erwähnt in Ressourcendatei kompiliert wurden.

Bitte überprüfen Sie diese Code-Ausschnitte von AOSP:

public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
    final Resources res = getContext().getResources();
    if (DEBUG) {
        Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                + Integer.toHexString(resource) + ")");
    }

    final XmlResourceParser parser = res.getLayout(resource);
    try {
        return inflate(parser, root, attachToRoot);
    } finally {
        parser.close();
    }
}

Resources.getLayout lädt den XML-Ressourcenparser

public XmlResourceParser getLayout(int id) throws NotFoundException {
    return loadXmlResourceParser(id, "layout");
}

XmlResourceParser loadXmlResourceParser(int id, String type)
        throws NotFoundException {
    synchronized (mAccessLock) {
        TypedValue value = mTmpValue;
        if (value == null) {
            mTmpValue = value = new TypedValue();
        }
        getValue(id, value, true);
        if (value.type == TypedValue.TYPE_STRING) {
            return loadXmlResourceParser(value.string.toString(), id,
                    value.assetCookie, type);
        }
        throw new NotFoundException(
                "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
                + Integer.toHexString(value.type) + " is not valid");
    }
}

getValue verwendet AssetManager 's getResourceValue und ruft die native Variable loadResourceValue auf. Diese native Methode ruft die getResource - Methode von ResTable auf, um XML-Zeichenfolgen in der Ressourcendatei abzurufen.

2
Wonil
Use appt for Android-sdk (ex:- /build-tools/27.0.3/aapt )

 run given script and get resources.arsc file content
./aapt dump resources ./debug.apk

Package Groups (1)
Package Group 0 id=0x7f packageCount=1 name=com.dianping.example.activity
  Package 0 id=0x7f name=com.dianping.example.activity
    type 1 configCount=3 entryCount=1
      spec resource 0x7f020000 com.example.activity:drawable/ic_launcher: flags=0x00000100
      config mdpi-v4:
        resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000000 (s=0x0008 r=0x00)
      config hdpi-v4:
        resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000001 (s=0x0008 r=0x00)
      config xhdpi-v4:
        resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000002 (s=0x0008 r=0x00)
    type 2 configCount=1 entryCount=1
      spec resource 0x7f030000 com.dianping.example.activity:string/app_name: flags=0x00000000
      config (default):
        resource 0x7f030000 com.dianping.example.activity:string/app_name: t=0x03 d=0x00000003 (s=0x0008 r=0x00)

Dieser Link könnte helfen http://elinux.org/Android_aapt