Подтвердить что ты не робот

Скомпилированные ресурсы Android - resources.arsc

Я пытаюсь выяснить, что значит "компилировать ресурсы".

Что я сделал, чтобы понять эту проблему:

Я прочитал много статей на эту тему, но не нашел простого ответа. Лучшее, что я прочитал, было: Как работает сопоставление ресурсов Android и идентификатора ресурсов? ,

Как я это понимаю

Насколько я понимаю, когда мы компилируем наш проект с помощью ANT (Eclipse) или Gradle (AS). Мы используем инструмент под названием aapt - Android Asset Packaging Tool, который: используется для генерации уникальных идентификаторов для каждого из наших ресурсов, таких как макеты, стили и т.д., И для сохранения их в справочной таблице. Затем он сохраняет эту таблицу поиска, генерируя два файла:

  1. Он генерирует файл R.java с этими уникальными идентификаторами, чтобы мы могли использовать наши ресурсы из нашего кода Java во время компиляции.
  2. Он генерирует файл resources.arsc, который можно найти в файле resources *.ap_. Этот файл resources.arsc будет позже упакован с помощью apktool в apk.
    Этот формат файла arsc - это формат, который будет легко отображаться и анализироваться устройством во время выполнения.

Пример:

Итак, чтобы сделать это просто: допустим, у меня есть это в моем activity_main.xml:

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

И я звоню из моего onCreate, используя:

findViewById(R.id.my_textView)

В моем файле R.java я увижу:

public static final int my_textView=0x7f08003f;

Использование: aapt dump ресурсов на сгенерированном apk. Я вижу, что он содержит две строки с my_textView: ec resource 0x7f08003f com.example.lizi.liortest2: id/my_textView: flags = 0x00000000 resource 0x7f08003f com.example.lizi.liortest2: id/my_textView: t = 0x12 d = 0x00000000 (s = 0x0008 r = 0x00)

Что я не понимаю

Я бы подумал, что этот файл resources.arsc будет содержать не только идентификатор ресурса, но и все свойства, которые я определил для представления, например, android: layout_width = "wrap_content".

Так что теперь во время выполнения, когда виртуальная машина пытается запустить findViewById(R.id.my_textView) Как он узнает, какое представление получить/свои свойства создать?

Я просто не могу понять, как это работает... Разве эта таблица поиска не должна содержать также данные свойств? И что это за номер 0x7f08003f? (Должно ли оно представлять значение, которое впоследствии будет сопоставлено с физической памятью, в которой будет храниться объект?)

4b9b3361

Ответ 1

TL; DR: с помощью компилятора Android (aapt) узлы xml будут переведены в классы Java и соответствующие атрибуты в числовые идентификаторы. Среда выполнения Android работает с этими идентификаторами для создания экземпляров классов с целью создания представлений.

TL, R

Запустите эту команду, чтобы сбросить двоичный XML
aapt d xmltree apk_file_name res/layout/activity_main.xml (aapt можно найти в android-sdk-dir/build-tools/23.0.2/aapt.exe)

Это покажет узлы xml (например, LinearLayout, RelativeLayout и т.д.) С их атрибутами (например, android:layout_width, android:layout_height) и их значения. Обратите внимание, что там можно match_parent константы match_parent (числовое значение 0xffffffff или -1) или wrap_content (числовое значение 0xfffffffe или -2).

Фактически, вы можете использовать эту команду для любых других XML файлов в apk, например, AndroidManifest.xml or layout files

Файл apk - это просто zip-архив, содержащий все файлы классов java (classes.dex), все скомпилированные файлы ресурсов и файл с именем resources.arsc. Этот файл resource.arsc содержит всю мета-информацию о ресурсах, узлах xml (например, LinearLayout, RelativeLayout и т.д.), Их атрибутах (например, android:layout_width), id ресурсов. Эти id ресурсов относятся к реальным ресурсам в apk файле. Атрибуты разрешаются в значение во время выполнения. Процесс разрешения подходит для любого перенаправления (@dimen/... вместо 4dp или @color/... в отличие от "#FFaabbcc") и возвращает используемое значение (значение dimen разрешается не так, как значение color).

Что такое скомпилированный XML файл: скомпилированный XML файл - это тот же XML файл, ссылки на ресурсы которого изменены на соответствующие ids. Например, ссылка @string/ok будет заменена на 0x7f000001. Кроме того, атрибуты из пространства имен android изменяются на их соответствующие целочисленные значения (например, wrap_content изменяется на 0xfffffffe или -2)

Как Android разрешает ресурсы во время выполнения: метод inflater.inflate() анализирует скомпилированный XML файл и создает иерархию представления путем создания экземпляров XML-узлов. Каждый из узлов xml создается классом java (например, LinearLayout.java, RelativeLayout.java). Чтобы создать экземпляр, инфлятор анализирует скомпилированный XML файл, собирает все атрибуты узла и создает упакованную структуру типа AttributeSet. Этот AttributeSet передается конструктору класса. Конструктор класса отвечает за обход AttributeSet и разрешение каждого из значений атрибута.

Например, для макета, содержащего RelativeLayout, inflater будет упаковывать layout_width и layout_height в AttributeSet и передавать его конструктору RelativeLayout (контекстный контекст, атрибуты AttributeSet, int defStyleAttr, int defStyleRes). В этом случае некоторые атрибуты и их значения разрешаются с помощью RelativeLayout.initFromAttributes(), а остальные - с помощью родительского ViewGroup.initFromAttributes().

android:id представления - это просто еще один атрибут. Инфлятор хранит идентификатор каждого представления, вызывая setId(id) для этого представления после создания экземпляра.

Теперь, чтобы ответить на ваш вопрос, R.id - это массив java, а my_textview - это целое число в этом массиве. id представления my_textview - это целое число (начинается с 0x7f). Метод findViewById() выполняет поиск в глубину в этой иерархии представлений, чтобы найти соответствующее представление.

Надеюсь это поможет. Ссылка, которую вы указали в своем вопросе, уже отвечает на то, как aapt генерирует идентификаторы.

Это замечательная система управления ресурсами для устройств с различными вариациями. Более того, реализация действительно быстрая !! Основываясь на этом, он позволяет реализовать функциональность более высокого уровня (например, наложение ресурсов времени выполнения)

Ответ 2

LayoutInflater раздуть представление, используя XML-строки. XML-строки, скомпилированные в файл ресурсов, как вы упомянули в своем вопросе.

Пожалуйста, проверьте эти фрагменты кода 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 загружает XML-парсер ресурсов

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 использует AssetManager getResourceValue и он вызывает собственный метод loadResourceValue. Этот собственный метод вызывает метод ResTable getResource, чтобы получить строки XML, хранящиеся в файле ресурсов.

Ответ 3

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)

Эта ссылка может помочь http://elinux.org/Android_aapt