Análise superficial do Android: mk preset AAR, arquivos SO, pacotes de APP e assinaturas

1. Como fazer referência a arquivos AAR no Android.mk

No desenvolvimento Android, muitas vezes é necessário usar bibliotecas de terceiros, que geralmente são fornecidas na forma de AAR ou JAR. Neste artigo, detalharemos como fazer referência a arquivos AAR em arquivos Android.mk.

Introdução ao arquivo AAR

Os arquivos AAR (Android Archive) são o formato de empacotamento dos projetos de biblioteca Android. Eles incluem classes Java, arquivos de recursos, arquivos de manifesto e arquivos de biblioteca local opcionais. Os arquivos AAR são uma maneira conveniente de distribuir bibliotecas Android porque contêm todos os recursos e códigos exigidos pela biblioteca.

Faça referência a arquivos AAR em Android.mk

Para referenciar um arquivo AAR no Android.mk, você precisa usar LOCAL_STATIC_JAVA_AAR_LIBRARIESvariáveis ​​para especificar o alias do arquivo AAR, depois usar LOCAL_PREBUILT_STATIC_JAVA_LIBRARIESvariáveis ​​para especificar a localização do arquivo AAR e, finalmente, usá-las include $(BUILD_MULTI_PREBUILT)para compilar o arquivo AAR.

Se o arquivo AAR contiver um arquivo de biblioteca local (.so), você também precisará LOCAL_JNI_SHARED_LIBRARIESespecificar o nome do módulo do arquivo de biblioteca local na variável e LOCAL_MULTILIBespecificar o número de bits (32 ou 64) do arquivo de biblioteca local na variável .

Se o arquivo AAR contiver outros arquivos JAR, você também precisará LOCAL_STATIC_JAVA_LIBRARIESespecificar o alias do arquivo JAR na variável e LOCAL_PREBUILT_STATIC_JAVA_LIBRARIESo local do arquivo JAR na variável.

Aqui está um exemplo detalhado de um Android.mk referenciando um arquivo AAR:

# 定义当前模块的相对路径
LOCAL_PATH := $(call my-dir)

# 清除一些变量的值,但是LOCAL_PATH除外
include $(CLEAR_VARS)

# 指定当前待编译模块的名称
LOCAL_MODULE := my-app

# 指定当前模块的源文件
LOCAL_SRC_FILES := MainActivity.java

# 指定当前模块依赖的aar文件的别名
LOCAL_STATIC_JAVA_AAR_LIBRARIES := my-lib

# 指定当前模块依赖的其他模块
LOCAL_SHARED_LIBRARIES := liblog

# 指定当前模块的编译选项
LOCAL_CFLAGS := -Wall -Werror

# 指定当前模块的链接选项
LOCAL_LDFLAGS := -Wl,-z,nocopyreloc

# 指定当前模块的目标类型,可以是静态库、动态库、可执行文件或者Java库等
include $(BUILD_PACKAGE)

# 声明aar文件的位置
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES += my-lib:libs/my-lib.aar
include $(BUILD_MULTI_PREBUILT)

# 如果aar文件包含了本地库文件(.so),还需要在下面声明本地库文件的模块名、源文件和路径,例如:
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE := libmy-lib
LOCAL_SRC_FILES := libs/armeabi-v7a/libmy-lib.so


LOCAL_MODULE_PATH := $(TARGET_OUT)/lib
include $(BUILD_PREBUILT)

Gerar arquivo AAR

Se quiser gerar um arquivo AAR, você pode compilar o arquivo JAR primeiro e depois compilar o arquivo AAR. Aqui está um exemplo:

make out/target/common/obj/JAVA_LIBRARIES/YourLibName_intermediates/javalib.jar
make out/target/common/obj/JAVA_LIBRARIES/YourLibName_intermediates/javalib.aar

Após executar o comando acima, você pode out/target/common/obj/JAVA_LIBRARIES/YourLibName_intermediates/encontrar o arquivo AAR gerado no diretório.

2. Métodos para referenciar e gerar arquivos SO em Android.mk

No desenvolvimento Android, bibliotecas de terceiros são frequentemente usadas, e essas bibliotecas geralmente são fornecidas na forma de SO (Shared Object). Neste artigo, detalharemos como referenciar e gerar arquivos SO em arquivos Android.mk.

Introdução aos arquivos SO

Os arquivos SO são arquivos de biblioteca de vínculo dinâmico, que podem ser compartilhados por vários aplicativos e também podem conter código local e outros arquivos SO. Um arquivo SO é uma maneira conveniente de distribuir uma biblioteca Android porque contém todos os recursos e códigos exigidos pela biblioteca.

Gere arquivo SO em Android.mk

Para gerar um arquivo SO no Android.mk, você precisa usar LOCAL_SRC_FILESvariáveis ​​para especificar o arquivo de origem, depois usar LOCAL_MODULEvariáveis ​​para especificar o nome do módulo e, finalmente, usá-las include $(BUILD_SHARED_LIBRARY)para compilar o arquivo SO.

@lib maneira de referenciar arquivos SO

@libO método é um método que especifica como carregar o arquivo SO no apk quando o apk está em execução. Ele pode evitar a operação de descompactar o arquivo SO no apk e copiá-lo para o diretório lib. No entanto, se houver vários arquivos SO no apk e nem todos os arquivos SO suportarem a mesma plataforma (como arm64-v8a ou armeabi-v7a), o método pode fazer com que o arquivo SO correspondente não seja encontrado e um erro @libocorrerá ser relatado.

Para resolver este problema, existem duas maneiras possíveis:

  • Método 1: Especifique em Android.mk apenas as plataformas suportadas para compilação, por exemplo:
ifeq ($(TARGET_ARCH), arm)
LOCAL_PREBUILT_JNI_LIBS := \
    @lib/armeabi-v7a/liba.so \
    @lib/armeabi-v7a/libb.so
else ifeq ($(TARGET_ARCH),arm64)
LOCAL_PREBUILT_JNI_LIBS := \
    @lib/arm64-v8a/liba.so \
    @lib/arm64-v8a/libb.so
endif
  • LOCAL_PREBUILT_JNI_LIBSMétodo 2: Use variáveis ​​em Android.mk para especificar LOCAL_PATHo caminho relativo ao arquivo SO em vez de usar @símbolos, por exemplo:
LOCAL_PREBUILT_JNI_LIBS := \
    lib/arm64-v8a/liba.so \
    lib/arm64-v8a/libb.so

Faça referência a arquivos SO em Android.mk

Para referenciar um arquivo SO no Android.mk, você precisa usar LOCAL_SHARED_LIBRARIESvariáveis ​​para especificar o nome do módulo do arquivo SO, depois usar LOCAL_PREBUILT_JNI_LIBSvariáveis ​​para especificar a localização do arquivo SO e, finalmente, usá-las include $(BUILD_PREBUILT)para compilar o arquivo SO.

Se o arquivo SO for de 32 ou 64 bits, você também precisará LOCAL_MULTILIBespecificar o número de bits na variável, por exemplo:

LOCAL_MULTILIB := 32

ou

LOCAL_MULTILIB := 64

Aqui está um exemplo detalhado de um Android.mk referenciando um arquivo SO:

# 定义当前模块的相对路径
LOCAL_PATH := $(call my-dir)

# 清除一些变量的值,但是LOCAL_PATH除外
include $(CLEAR_VARS)

# 指定当前待编译模块的名称
LOCAL_MODULE := my-app

# 指定当前模块的源文件
LOCAL_SRC_FILES := MainActivity.java

# 指定当前模块依赖的so文件的模块名
LOCAL_SHARED_LIBRARIES := libtest1 libtest2 libtest3

# 指定当前模块的编译选项
LOCAL_CFLAGS := -Wall -Werror

# 指定当前模块的链接选项
LOCAL_LDFLAGS := -Wl,-z,nocopyreloc

# 指定当前模块的目标类型,可以是静态库、动态库、可执行文件或者Java库等
include $(BUILD_PACKAGE)

# 声明so文件的位置,有两种方式:

# 方式一:使用LOCAL_PREBUILT_JNI_LIBS变量,指定so文件相对于LOCAL_PATH的路径,例如:
include $(CLEAR_VARS)
LOCAL_PREBUILT_JNI_LIBS := \
    lib/arm64-v8a/libtest1.so \
    lib/arm64-v8a/libtest2.so \
    lib/arm64-v8a/libtest3.so
include $(BUILD_MULTI_PREBUILT)

# 方式二:使用LOCAL_MODULE和LOCAL_SRC_FILES变量,指定so文件的模块名和源文件,然后使用include $(BUILD_PREBUILT)来编译so文件,例如:
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE := libtest1
LOCAL_SRC_FILES := libs/armeabi-v7a/libtest1.so
LOCAL_MODULE_PATH := $(TARGET_OUT)/lib
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED

_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE := libtest2
LOCAL_SRC_FILES := libs/armeabi-v7a/libtest2.so
LOCAL_MODULE_PATH := $(TARGET_OUT)/lib
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE := libtest3
LOCAL_SRC_FILES := libs/armeabi-v7a/libtest3.so
LOCAL_MODULE_PATH := $(TARGET_OUT)/lib
include $(BUILD_PREBUILT)

Como lidar com vários arquivos SO em um APK
. No desenvolvimento Android, um APK pode conter vários arquivos SO, e esses arquivos SO podem ser distribuídos em diretórios diferentes. Pode ser problemático processar esses arquivos SO. No entanto, existem alguns métodos que você pode usar para simplificar esse processo.

Método 1: use instruções de loop para descompactar automaticamente todos os arquivos SO

No Android.mk, você pode usar uma instrução de loop para iterar por todos os arquivos SO no APK e usar LOCAL_PREBUILT_JNI_LIBSvariáveis ​​para especificar LOCAL_PATHo caminho relativo ao arquivo SO. Aqui está um exemplo:

# 清空临时变量JNI_LIBS
JNI_LIBS :=
# 当前目录递归搜索
$(foreach FILE,$(shell find $(LOCAL_PATH)/lib/ -name *.so), $(eval JNI_LIBS += $(FILE)))
# 获取搜索文件目录集(相对目录)
LOCAL_PREBUILT_JNI_LIBS := $(subst $(LOCAL_PATH),,$(JNI_LIBS))

Desta forma, todos os arquivos SO do APK podem ser descompactados automaticamente.

Método 2: use o símbolo @ para evitar a descompactação de todos os arquivos SO

No Android.mk, você também pode usar @símbolos para especificar que o arquivo SO no APK será carregado quando o APK estiver em execução, sem descompactá-lo. Aqui está um exemplo:

ifeq ($(TARGET_ARCH), arm)
LOCAL_PREBUILT_JNI_LIBS := \
    @lib/armeabi-v7a/liba.so \
    @lib/armeabi-v7a/libb.so \
    ...
else ifeq ($(TARGET_ARCH),arm64)
LOCAL_PREBUILT_JNI_LIBS := \
    @lib/arm64-v8a/liba.so \
    @lib/arm64-v8a/libb.so \
    ...
endif

Desta forma, você pode evitar a descompactação de todos os arquivos SO no APK.

A diferença entre usar o símbolo @ e não usar o símbolo @

No Android.mk, existem algumas diferenças entre usar @símbolos e não usar símbolos:@

  • O uso @de símbolos pode melhorar o desempenho porque não há necessidade de descompactar e copiar arquivos SO e também pode economizar espaço porque não há necessidade de armazenar arquivos SO redundantes.
  • Não usar @símbolos pode melhorar a compatibilidade, porque os arquivos SO correspondentes podem ser fornecidos para diferentes plataformas sem considerar se há arquivos SO para as plataformas correspondentes no APK.

3. APK predefinido, arquivos SO e assinaturas em Android.mk

No desenvolvimento de sistemas Android, muitas vezes é necessário predefinir alguns arquivos de aplicativos (APK) e bibliotecas (SO) e especificar assinaturas para esses arquivos de aplicativos e bibliotecas. Essas operações geralmente são feitas no arquivo Android.mk. Este artigo apresentará detalhadamente os métodos e precauções para essas operações.

APK predefinido

Existem duas maneiras de predefinir o APK: uma é predefinir o aplicativo com código-fonte e a outra é predefinir o APK sem código-fonte.

Aplicativo predefinido com código-fonte

O método de pré-configurar um aplicativo com código-fonte é colocar o código-fonte do aplicativo em algum lugar da árvore de origem, como o diretório vendor/xxx/appsou e packages/apps, em seguida, criar um arquivo Android.mk no diretório do aplicativo e especificar as variáveis ​​relevantes e regras de compilação . Por exemplo:

# 定义当前模块的相对路径
LOCAL_PATH := $(call my-dir)

# 清除一些变量的值,但是LOCAL_PATH除外
include $(CLEAR_VARS)

# 指定当前待编译模块的名称
LOCAL_MODULE := my-app

# 指定当前模块的源文件
LOCAL_SRC_FILES := MainActivity.java

# 指定当前模块依赖的其他模块
LOCAL_SHARED_LIBRARIES := liblog

# 指定当前模块的编译选项
LOCAL_CFLAGS := -Wall -Werror

# 指定当前模块的链接选项
LOCAL_LDFLAGS := -Wl,-z,nocopyreloc

# 指定当前模块的目标类型,可以是静态库、动态库、可执行文件或者Java库等
include $(BUILD_PACKAGE)

APK predefinido sem código fonte

A maneira de predefinir um apk sem código-fonte é colocar o apk em algum lugar da árvore de origem, como vendor/xxx/appsum diretório, e então criar um arquivo Android.mk no diretório apk, usar LOCAL_PREBUILT_STATIC_JAVA_LIBRARIESvariáveis ​​para especificar o caminho relativo ao apk LOCAL_PATHe use LOCAL_STATIC_JAVA_LIBRARIESvariáveis ​​​​para definir o alias do apk. Por exemplo:

# 定义当前模块的相对路径
LOCAL_PATH := $(call my-dir)

# 清除一些变量的值,但是LOCAL_PATH除外
include $(CLEAR_VARS)

# 指定当前待编译模块的名称
LOCAL_MODULE := my-app

# 指定当前模块依赖的预置apk文件
LOCAL_STATIC_JAVA_LIBRARIES := my-app-prebuilt

# 指定当前模块的目标类型,可以是静态库、动态库、可执行文件或者Java库等
include $(BUILD_PACKAGE)

# 声明预置apk文件的位置
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES += my-app-prebuilt:my-app.apk
include $(BUILD_MULTI_PREBUILT)

Arquivo SO predefinido

Existem duas maneiras de predefinir arquivos SO, uma é predefinir com código-fonte e a outra é predefinir sem código-fonte.

Predefinido assim com o código-fonte

O método para predefinir isso com o código-fonte é colocar o código-fonte em algum lugar da árvore de origem, como o diretório vendor/xxx/libsou external/xxxe, em seguida, criar um arquivo Android.mk no diretório so e especificar as variáveis ​​relevantes e as regras de compilação. Por exemplo:

# 定义当前模块的相对路径
LOCAL_PATH := $(call my-dir)

# 清除一些变量的值,但是LOCAL_PATH除外
include $(CLEAR_VARS)

# 指定当前待编译模块的名称
LOCAL_MODULE := libtest

# 指定当前模块的源文件
LOCAL_SRC_FILES := test.c

# 指定当前模块依赖的其他模块
LOCAL_SHARED_LIBRARIES := libcutils liblog

# 指定当前模块的编译选项
LOCAL_CFLAGS := -Wall -Werror

# 指定当前模块的链接选项
LOCAL_LDFLAGS := -Wl,-z,nocopyreloc

# 指定当前模块的目标类型,可以是静态库、动态库、可执行文件或者Java库等
include $(BUILD_SHARED_LIBRARY)

Predefinido sem código fonte

A maneira de predefinir so sem código-fonte é colocá-lo em algum lugar da árvore de origem, como vendor/xxx/libsum diretório, e então criar um arquivo Android.mk no diretório so e usar LOCAL_PREBUILT_JNI_LIBSvariáveis ​​para especificar o caminho relativo ao arquivo so LOCAL_PATH, ou use @o símbolo para especificar o arquivo so no apk a ser carregado quando o apk for executado. Por exemplo:

# 定义当前模块的相对路径
LOCAL_PATH := $(call my-dir)

# 清除一些变量的值,但是LOCAL_PATH除外
include $(CLEAR_VARS)

# 指定当前待编译模块的名称
LOCAL_MODULE := my-app

# 指定当前模块依赖的预置so文件
LOCAL_SHARED_LIBRARIES := libtest1 libtest2 libtest3

# 指定当前模块的目标类型,可以是静态库、动态库、可执行文件或者Java库等
include $(BUILD_PACKAGE)

# 声明预置so文件的位置,有两种方式:

# 方式一:使用LOCAL_PREBUILT_JNI_LIBS变量,指定so文件相对于LOCAL_PATH的路径,例如:
include $(CLEAR_VARS)
LOCAL_PREBUILT_JNI_LIBS := \
    lib/arm64-v8a/libtest1.so \
    lib/arm64-v8a/libtest2.so \
    lib/arm64-v8a/libtest3.so
include $(BUILD_MULTI_PREBUILT)

# 方式二:使用@符号,指定apk运行时加载apk中的so文件,例如:
ifeq ($(TARGET_ARCH), arm)
LOCAL_PREBUILT_JNI_LIBS := \
    @lib/armeabi-v7a/libtest1.so \
    @lib/armeabi-v7a/libtest2.so \
    @lib/armeabi-v7a/libtest3.so
else ifeq ($(TARGET_ARCH),arm64)
LOCAL_PREBUILT_JNI_LIBS := \
    @lib/arm64-v8a/libtest1.so \
    @lib/arm64-v8a/libtest2.so \
    @lib/arm64-v8a/libtest3.so
endif

Diretório de arquivos APK e SO predefinidos

Os diretórios de arquivos APK e SO predefinidos podem ser divididos em três tipos: diretório system/app, diretório system/priv-app e diretório data/app.

diretório sistema/aplicativo

Os arquivos APK e SO predefinidos no diretório system/app são aplicativos e bibliotecas comuns do sistema. Os usuários não podem desinstalá-los, mas podem atualizá-los. APKs e arquivos SO predefinidos no diretório system/app precisam especificar variáveis ​​no arquivo Android.mk LOCAL_MODULE_PATH := $ (TARGET_OUT_APPS)e adicionar esta frase ao arquivo device/xxxx/device.mk PRODUCT_PACKAGES += <app_name>para especificar o nome do aplicativo a ser empacotado na imagem do sistema .

diretório system/priv-app

Os arquivos APK e SO predefinidos no diretório system/priv-app são aplicativos e bibliotecas privilegiadas do sistema. Os usuários não podem desinstalá-los, mas podem atualizá-los e ter permissões especiais. Os arquivos APK e SO predefinidos para o diretório system/priv-app precisam especificar variáveis ​​no arquivo Android.mk LOCAL_MODULE_PATH := $ (TARGET_OUT_PRIVILEGED_APPS)e adicionar esta frase no arquivo device///device.mk PRODUCT_PACKAGES += <app_name>para especificar o nome do aplicativo a ser empacotado na imagem do sistema .

diretório de dados/aplicativo

Os arquivos APK e SO predefinidos no diretório data/app são aplicativos e bibliotecas comuns, que podem ser desinstalados e atualizados pelos usuários e serão limpos após a restauração das configurações de fábrica. Os arquivos APK e SO predefinidos no diretório data/app precisam especificar variáveis ​​no arquivo Android.mk LOCAL_MODULE_PATH := $ (TARGET_OUT_DATA_APPS)e adicionar esta frase no arquivo device///device.mk PRODUCT_PACKAGES += <app_name>para especificar o nome do aplicativo a ser empacotado na imagem do sistema .

Especifique a assinatura

As assinaturas que podem ser especificadas no arquivo Android.mk são as seguintes:

  • Plataforma: Indica o uso de arquivos de assinatura de plataforma, geralmente utilizados para aplicações de sistema ou aplicações privilegiadas.
  • compartilhado: Indica o uso de um arquivo de assinatura compartilhado, geralmente usado para aplicativos que compartilham IDs de usuário.
  • media: Indica o uso de arquivos de assinatura de mídia, geralmente usados ​​para aplicações relacionadas à mídia.
  • testkey: indica a utilização de arquivos de assinatura de teste, geralmente utilizados para aplicações em fase de desenvolvimento.
  • PRÉ-ASSINADO: Indica que um arquivo apk pré-assinado é usado e não precisa ser assinado novamente.
  • <keystore_file>: Indica o uso do arquivo de assinatura especificado, que pode ser um caminho relativo ou absoluto.

A maneira de especificar uma assinatura é usar uma variável no arquivo Android.mk LOCAL_CERTIFICATEpara especificar o nome ou caminho do arquivo de assinatura. Por exemplo:

# 使用平台签名
LOCAL_CERTIFICATE := platform

# 使用共享签名
LOCAL_CERTIFICATE := shared

# 使用媒体签名
LOCAL_CERTIFICATE := media

# 使用测试签名
LOCAL_CERTIFICATE := testkey

# 使用预先签名的apk
LOCAL_CERTIFICATE := PRESIGNED

# 使用自定义签名
LOCAL_CERTIFICATE := mykey.keystore

Se nenhuma assinatura for especificada, o padrão será assinatura testkey.

A diferença entre assinaturas

A assinatura especificada no arquivo Android.mk é usada para assinar o arquivo apk predefinido para que ele possa ser executado no sistema ou acessar permissões específicas.

  • A assinatura da plataforma é usada para assinar os aplicativos principais da plataforma. Esses aplicativos completam as funções principais do sistema. O UID do processo no qual eles estão localizados é o sistema e eles podem acessar APIs no nível do sistema. Por exemplo, aplicativo de configurações, aplicativo de telefone, etc.
  • A assinatura de mídia é usada para assinar aplicativos relacionados à mídia. Esses aplicativos fazem parte de mídia/download. O UID do processo no qual eles estão localizados é android.media e eles podem acessar APIs relacionadas à mídia. Por exemplo, aplicativo de câmera, aplicativo de música, etc.
  • Assinaturas compartilhadas são usadas para assinar aplicativos que podem compartilhar dados com o processo inicial/contatos. O UID do processo em que estão localizados é android.uid.shared, e eles podem acessar APIs relacionadas aos dados compartilhados. Por exemplo, aplicativo de desktop, aplicativo de contato, etc.
  • As assinaturas Testkey são usadas para assinar aplicativos em fase de teste. Elas não requerem UIDs ou permissões de processo específicas e só podem ser executadas na versão de desenvolvimento do sistema. Por exemplo, aplicativo HelloWorld, etc.
  • A assinatura PRESIGNED é usada para assinar arquivos apk pré-assinados. Eles não precisam ser assinados novamente e podem ser instalados diretamente no sistema. Por exemplo, aplicativos de terceiros, etc.
  • A assinatura <keystore_file> é usada para assinar arquivos de assinatura personalizados. Eles podem especificar qualquer arquivo ou caminho de keystore. Por exemplo, mykey.keystore, etc.

Resumir

No desenvolvimento de sistemas Android, a predefinição de arquivos APK e SO e a especificação de assinaturas são operações comuns. Compreender os métodos e precauções para essas operações pode ajudá-lo a desenvolver melhor o sistema Android. Este artigo explica como provisionar arquivos APK e SO no arquivo Android.mk e como especificar diferentes tipos de assinaturas. Espero que este artigo seja útil para você. Se você tiver alguma dúvida, deixe-a na área de comentários.

Acho que você gosta

Origin blog.csdn.net/SHH_1064994894/article/details/131490259
Recomendado
Clasificación