首页 使用Android Studio开发Android系统应用
文章
取消

使用Android Studio开发Android系统应用

一、概述

在实际开发中,大多数情况是使用AndroidStudio来开发Android系统应用,本文将介绍如何使用AndroidStudio开发Android系统应用。

二、开发步骤

2.1 编译framework

Android系统APP可以使用很多隐藏的API,所以需要从AOSP源码中把包含隐藏API的jar包编译出来。首先进入源码目录,执行如下命令:

1
2
3
source build/envsetup.sh
lunch rice14-eng
make framework

最终编译产物在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/目录下,包含隐藏API的jar包名称是classes.jar

2.2 创建APP项目

做系统开发选择AndroidStudio版本比较重要,我们是基于Android 10.0.0 r41的,所以选择的Android Studio 3.6.3版本,该版本与Android 10.0.0 r41发布时间相接近。应用基本信息如下:

20240405110000

新建好项目之后,在AndroidManifest.xml文件的根节点添加以下属性

1
android:sharedUserId="android.uid.system"

这个代表是系统应用。现在我们在APP项目目录下新建一个framework目录,将编译产物classes.jar拷贝进去并重命名为framework.jar,然后修改项目级别的build.gradle文件,在allprojects添加如下内容:

1
2
3
4
5
6
7
8
9
gradle.projectsEvaluated {
    tasks.withType(JavaCompile) {
        Set<File> fileSet = options.bootstrapClasspath.getFiles()
        List<File> newFileList = new ArrayList<>();
        newFileList.add(new File("./app/framework/framework.jar"))
        newFileList.addAll(fileSet)
        options.bootstrapClasspath = files(newFileList.toArray())
    }
}

接下来在app的build.gradle中的dependencies中添加如下内容:

1
2
3
4
5
6
7
8
9
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    compileOnly files('framework/framework.jar')
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

接着我们需要制作系统签名,这里使用 keytool-importkeypair (下载地址 https://github.com/getfatday/keytool-importkeypair)签名工具,刚脚本放入PATH目录下。接着进入系统源码下的 build/target/product/security 路径,执行如下命令:

1
keytool-importkeypair -k ./platform.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform

k 表示要生成的签名文件的名字,这里命名为 platform.keystore -p 表示要生成的 keystore 的密码,这里是 android -pk8 表示要导入的 platform.pk8 文件 -cert 表示要导入的platform.x509.pem -alias 表示给生成的 platform.keystore 取一个别名,这是命名为 platform。

接着,把生成的签名文件 platform.keystore 拷贝到 Android Studio 项目的 app 目录下,然后在 app/build.gradle 中的android节点添加签名的配置信息:

1
2
3
4
5
6
7
8
signingConfigs {
    sign {
        storeFile file('platform.keystore')
        storePassword 'android'
        keyAlias = 'platform'
        keyPassword 'android'
    }
}

同时anroid节点下的buildTypes节点配置变更如下:

1
2
3
4
5
6
7
8
9
10
11
12
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.sign
    }
    
    debug {
        minifyEnabled false
        signingConfig signingConfigs.sign
    }
}

三、修改源代码

3.1 调用系统API

我们修改MainActivityonCreate方法代码,用于调用系统的隐藏API,如下

1
2
3
4
5
6
7
8
9
10
11
12
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 调用一个系统级别API
        SystemClock.setCurrentTimeMillis(0);
        // 访问一个系统级别的变量
        Log.d("SecondSystemApp", "" + AudioSystem.STREAM_ACCESSIBILITY);
    }
}

3.2 Service保活

在java代码目录新增一个TestService类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package tech.webcoding.secondsystemapp;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class TestService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        new Thread() {
            @Override
            public void run() {
                super.run();
                while (true) {
                    Log.d("TestService", "Test Service is running");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}

为了验证系统APP能够保活,我们在AndroidManifest.xml文件中的application节点添加保活属性,并注册Service,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    <!-- 添加保活属性 -->
    android:persistent="true"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <!-- 注册Service -->
    <service
        android:name=".TestService"
        android:enabled="true"
        android:exported="true"/>

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

MainActivity启动Service,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 调用一个系统级别API
        SystemClock.setCurrentTimeMillis(0);
        // 访问一个系统级别的变量
        Log.d("SecondSystemApp", "" + AudioSystem.STREAM_ACCESSIBILITY);
        // 启动Service
        Intent intent = new Intent(this, TestService.class);
        startService(intent);
    }
}

四、调试验证

Android Studio 3.6.3这个版本它不会主动连模拟器,这是一个bug,因此我们需要在IDE的终端上执行adb connect 127.0.0.1主动连接模拟器。接下来点击运行程序的按钮,APP打开应用后,手动关掉应用后并观察日志,Service的日志正常输出,说明我们的APP已经成功保活了。如下图

20240405110001

本文由作者按照 CC BY 4.0 进行授权

在AOSP中添加系统APP

初识POSIX:理解和使用可移植操作系统接口