将Android Studio创建的一个apk工程放到Android15源码中构建

背景描述:

起初Android Studio创建的apk工程,为了方便系统版本发布和后期维护需要同时支持两种构建方式:

  • Android Studio Gradle构建 IDE界面环境,对习惯java环境变成的友好、UI设计方便看效果
  • Android15系统构建时自动构建 Soong构建 这种构建apk源码放在aosp系统源码中,作为一个普通的module来进行编译构建。对于平时中心在系统集成的同学友好,对版本管理也方便。

由于Android Studio创建的app工程有固定的文件结构,和Soong构建时文件结构组织会有些差异,所以做两套构建系统的兼容,主要从以下几个方面进行:

  1. 调整apk源码的目录结构,兼容Gradle构建和Soong构建
  2. 添加Soong构建相关的脚本
  3. 调整apk源码文件(包括ui相关脚本、res文件等), 使兼容Gradle构建和Soong构建

下面以具体例子来讲解自己是如何实现Androd Studio创建的CameraDemo.apk同时支持:

  • Windows11 Android Studio构建
  • Linux ubuntu aosp源码构建

1.Android Studio创建的CameraDemo Project

Android Studio创建一个新的工程,工程名为camerademo, 创建完成的工程文件结构如下:

bash 复制代码
├── app
│   ├── build.gradle
│   ├── libs
│   ├── proguard-rules.pro              
│   └── src
│       ├── androidTest/java/com/example/camerademo //测试程序目录
│       ├── main
│       │   ├── AndroidManifest.xml                 //声明camerademo所需权限等内容
│       │   ├── java/com/example/camerademo         //camerademo程序源码.java目录
│       │   └── res                                 //camerademo程序资源文件(ui, layout等)目录
│       └── test/java/com/example/camerademo        //test程序目录
├── build.gradle                                    //下边是gralde构建相关的脚本文件
├── gradle                              
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle

2.调整CameraDemo目录结构,兼容Soong构建

Soong编译的模块,构建目录结构如下:

bash 复制代码
aosp/vendor/amlogic/package/camerademo/
├── Android.bp                            //camerademo soong构建的脚本
├── AndroidManifest.xml                   //声明camerademo应用所需的权限和Activity
├── res                                   //camerademo应用资源文件
└── src/com/example/android/camera2demo/  //camerademo应用程序代码目录

基于上边Android Studio创建的camerademo工程,修改出兼容上边Soong编译模块目录结构, 修改后的兼容结构如下:

bash 复制代码
├── app
│   ├── build.gradle
│   ├── libs
│   ├── proguard-rules.pro              
│   └── src
│       ├── androidTest/java/com/example/camerademo //测试程序目录
│       ├── main
│       │   ├── AndroidManifest.xml                 //【gradle构建】声明camerademo所需权限等内容
│       │   ├── java/com/example/camerademo         //【gradle/soong构建】camerademo程序源码.java目录
│       │   └── res                                 //【gradle/soong构建】camerademo程序资源文件(ui, layout等)目录
│       └── test/java/com/example/camerademo        //test程序目录
├── build.gradle                                    //下边是gralde构建相关的脚本文件
├── gradle                              
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
├── settings.gradle
├── Android.bp                                     //【soong构建】构建配置脚本
├── AndroidManifest.xml                            //【soong构建】声明camerademo所需权限、Activity等
├── CleanSpec.mk                                   //【soong构建】make clean脚本  
├── src
│   └── com -> ../app/src/main/java/com/           //【soong构建】实现源码文件的软连接
├── res -> app/src/main/res                        //【soong构建】实现资源文件的软连接
└── keys                                           //【soong构建】签名证书文件
    ├── com.example.camerademo.avbpubkey
    ├── com.example.camerademo.pem
    ├── camerademo.jks
    ├── camerademo.p12
    ├── camerademo.pk8
    └── camerademo.x509.pem                                    

如上,camerademo project为了兼容soong构建,添加了6个文件:

  • Android.bp 配置camerademo构建参数
  • AndroidManifest.xml 声明camerademo权限等内容
  • src/com和res 这两个软链接使soong构建和gradle构建时src(源文件、资源文件)是同一份,后期维护修改只针对一份代码。
  • keys 目录存放的是soong构建系统进行apk打包签名时用到的文件。

3.添加CameraDemo到Soong构建系统

将CameraDemo添加到aosp源码构建系统需要加两个内容:

  1. 将camerademo添加到系统镜像(注意:非prebuild构建)
  2. 添加camerademo的构建脚本,即Android.bp

添加到系统镜像

假设,我们是基于amlogic/yukawa构建系统镜像。

bash 复制代码
#当前文件:android/device/amlogic/yukawa/device-yukawa.mk
#在设备mk文件中添加:

PRODUCT_PACKAGES += CameraDemo

如果之前镜像打包的时候已经带CameraDemo并且是prebuilt构建的,则需要从预构建列表中去掉对应的预构建配置:

camerademo soong构建之Android.bp

对应camerademo工程目录中的./Android.bp文件:

bash 复制代码
//
// Copyright (C) 2013 Google Inc.
//

package {
    // See: http://go/android-license-faq
    default_applicable_licenses: [
        "Android-Apache-2.0",
    ],
}

apex_key {
    name: "com.example.camera2demo.key",
    public_key: "keys/com.example.camerademo.avbpubkey",
    private_key: "keys/com.example.camerademo.pem",
}

android_app_certificate {
    name: "com.example.camerademo.certificate",
    certificate: "keys/vk",
}

apex_defaults {
    name: "com.example.camerademo.apex-defaults",
    key: "com.example.camerademo.key",
    certificate: ":com.example.camerademo.certificate",
}

android_app {
    name: "CameraDemo",
    sdk_version: "current",
    manifest: "AndroidManifest.xml",
    optimize: {
        enabled: true,
    },
    defaults: ["com.example.camerademo.apex-defaults"],
    privileged: true,

    static_libs: [
        "androidx.appcompat_appcompat",
        "com.google.android.material_material",
        "androidx.legacy_legacy-support-v13",
        "androidx.legacy_legacy-support-v4",
        "androidx.core_core",
        "android-ex-camera2-portability",
        "xmp_toolkit",
        "glide",
        "guava",
        "jsr305",
    ],

    srcs: [
        "src/**/*.java",
    ],

    resource_dirs: [
        "res",
    ],

    product_specific: true,
}

camerademo soong构建之AndroidManifest.xml

对应camerademo工程目录中的./AndroidManifest.xml文件, 是从Android Studio构建使用的AndroidManifest.xml文件拿过来的:

bash 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.camera2demo">
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

4.为CameraDemo添加签名配置

为了让soong构建的camerademo是签名后的.apk,需要为camerademo添加签名:

  1. 制作camerademo签名使用的密钥库文件
  2. camerademo构建脚本中添加签名配置

制作camerademo应用签名的密钥文件

有两种方法生成.jks文件:

  1. 使用Android Studio,通过界面配置生成.jks
  2. 使用jdk keytool命令行工具,生成.jks

方法1.使用Android Studio生成

注:根据自己需要配置好key,点击next选择应用的apk版本为debug或者relase。这是会生成一个.jks文件。

方法2.使用keytool命令行工具生成.jks

keytool工具是jdk自带的命令行工具,所以需要先配置好jdk环境。

bash 复制代码
$keytool -genkeypair -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias

参数说明:

  • -keystore:指定生成的.jks文件名
  • -alias:密钥别名(后续签名会用到)
  • -keyalg:密钥算法(推荐RSA)
  • -keysize:密钥大小(推荐2048)
  • -validity:有效期天数(单位:天)

执行后会提示输入密钥库密码、密钥密码以及一些个人信息。

将JKS转换成soong构建系统需要的格式

使用keytool和openssl将JKS转换为Android构建系统需要的格式:

bash 复制代码
##进入证书目录
#cd vendor/google/packages/apps/camerademo/keys

##从JKS导出P12格式
#keytools -importkeystore \
    -srckeystore camerademo.jsk \
    -destkeystore camerademo.p12 \
    -deststoretype PKCS12


##导出证书(PEM格式)
#openssl pkcs12 -in camerademo.p12 -nokeys -out camerademo.x509.pem

##导出私钥(PKCS8格式)
#openssl pkcs12 -in camerademo.p12 -nodes -nocerts \
    | openssl pkcs8 -topk8 -outform DER -out camerademo.pk8 -nocrypt

生成如下文件:

bash 复制代码
keys/
  ├── camerademo.jks        # 原始文件
  ├── camerademo.x509.pem   # 证书文件
  └── camerademo.pk8        # 私钥文件

camerademo构建脚本中添加签名配置

即如上Android.bp中的如下内容:

5.aosp源码方式编译CameraDemo

bash 复制代码
$cd android
$source build/envsetup.sh
$lunch xx-userdebug
$make camerademo
##或者
$cd /vendor/amlogic/package/camerademo
$mm
相关推荐
阿巴斯甜2 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker2 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95272 天前
Andorid Google 登录接入文档
android
黄林晴2 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_3 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android