作者: baron
环境搭建花了很久, 编写 app 调用 HelloManager 提供的服务. app 开发自然离不开 Android Studio. 这个工具是专门用来开发 app 的. 而不同版本之间对各个 api 的支持差异很大. 以下是我尝试使用过的不同版本的 Android Studio . 还有些被我删掉了. 总共试了十几个版本.只有一个成功了. 各版本下载地址.
本次实验成功使用的版本信息如下, 为 Android Studio 4.2 Beta 6
Android Studio 4.2 Beta 6
Build #AI-202.7660.26.42.7188722, built on March 6, 2021
Runtime version: 11.0.8+10-b944.6842174 amd64
VM: OpenJDK 64-Bit Server VM by N/A
Windows 10 10.0
GC: G1 Young Generation, G1 Old Generation
Memory: 1280M
Cores: 20
Registry: external.system.auto.import.disabled=true
对应的名字为 android-studio-ide-202.7188722-windows.exe
, 重要的事情说三遍, 一定要用这个版本, 一定要用这个版本, 一定要用这个版本 !!!. 这个破软件向下兼容性极差. =-=
双击 exe 文件, 会出现下面安装提示, 点击 next
这里记得勾选 android vitual device
.
接着设置安装路径, 我设置在 d 盘, 根据实际情况设置即可
接下来一直点 next 就行了
出现这个界面点击 cancel, 之后又是点击 next. 之后会提示配置 sdk 路径, 这里我选择默认 c 盘
接下来等待 sdk 的安装, 安装完成后界面如下.
到这里软件安装完成.
在打开新项目(project)之前要先配置 SDK manager
. 这一点很重要, 因为直接打开默认的 api 接口是 34 版本的, 而且使用的工具是也是 34 版本的.
如图所示在左下角打开 SDK manager
, 打开之后如下所示.
如图首先去掉 android api 34
然后勾选上 android 11
. 然后点击 SDK Tools
, 配置对应的工具
首先点击右下角 show package details
显示出详细的版本, 然后同样的把 34.0.0
去掉, 勾选上 30.0.2
和 30.0.3
. 之后点击 apply.
如图点击 next 进入安装. 等待安装完成
SKD Platforms
: 表示使用哪个 sdk , 安卓 11 对应的 sdk 是 30SDK Tools
: 和前面的版本需要对应下载完成之后回到前面, 点击创建新项目 project
选择一个 empty activity
.
语言选择 java, sdk 选择 Android 11, 之后点击 finish
这里选择 project 方便看代码
接下来会报错如下
到这里项目构建就结束了, 接下来就是配置项目解决报错
对目录结构有个了解. 此部分请参考 Android studio项目目录结构. 其中需要关注的目录如下.
目录 | 功能 |
---|---|
libs | 存放第三方 jar 包的目录, 我们要用我们自己的sdk编译出来包替换掉 as 中默认的包 |
MainActivity.java | 程序从这里开始运行, 可以理解为 c 语言的 main 函数 |
app/build.gradle | app 模块的构建配置, 包括 sdk 版本, 以及包含哪些 jar 包等 |
/build.gradle | 根目录下的 build.gradle 是整个项目的配置文件, 用来指定整具体使用哪个 gradle 插件 |
gradle-wrapper.properties | 指定了那个 gradle 工具 |
gradle:4.2.0
gradle 插件
, gradle 工具
, 和 java 版本(jdk版本)
之间的对应关系请参考 Android Studio Gradle插件版本与Gradle 版本对应关系.
有了上述知识之后我们开始配置我们的项目, 首先解决超时报错, 修改文件 gradle\-wrapper.properties
, 首先更换 gradle 工具的下载地址.
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-6.7.1-bin.zip
具体修改如图所示
然后打开根目录下 build.gradle
做如下修改
buildscript {
repositories {
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/google'}
maven { url 'https://maven.aliyun.com/repository/gradle-plugin'}
maven { url 'https://maven.aliyun.com/repository/public'}
google()
mavenCentral()
}
dependencies {
//classpath "com.android.tools.build:gradle:4.2.0-beta06"
classpath "com.android.tools.build:gradle:4.2.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
具体修改如图所示
完成之后点击右上角的 try again
, 这个选项只有选中这个文件才会出现, 所以要构建项目要先选中这个文件, 不然右上角是不会出现这个选项的. 点击之后等待项目构建完成, 这个构建的时间比较长. 编译完成之后会有如下警告.
这个警告没有任何影响, 假装没看见就行了, 不要去注释掉 jcenter()
, 注释掉会报错. 插上机器, 点击运行, 如下所示显示 hello world 就是编译成功了.
虽然编译成功了但是调用的接口是, gradle 工具提供的默认接口, 现在还没法调用, 我们需要我们的 app 调用我们 sdk 中添加的 hello 服务能编译通过, 得加入 sdk 中编译出来的 jar 包. 对应的路径
$ ls out/target/common/obj/JAVA_LIBRARIES/framework-minus-apex_intermediates/
classes-header.jar classes.jar javalib.jar
我们需要 classes.jar , 记得在编译之前要把这个删掉再编译, 不然这个可能不会更新的, 导致这个包里面没有更新接口. 把这个拷贝到 app 的 libs 目录, 并且改名为 framework.jar
, 然后在 app/gradle 中添加以下内容
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
Set<File> fileSet = options.bootstrapClasspath.getFiles()
List<File> newFileList = new ArrayList<>();
//JAVA语法,可连续调用,输入参数建议为相对路径
newFileList.add(new File("libs/framework.jar"))
//最后将原始参数添加
newFileList.addAll(fileSet)
options.bootstrapClasspath = files(
newFileList.toArray()
)
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
compileOnly files('libs/framework.jar')
}
修改如图所示
注意了设置里面需要将 “generate *imx” 勾选上用于创建自动创建 imx 文件, 这个文件用来调整使用的 sdk 的顺序. 可以在这里将我们的 jar 提前.接着在根目录下的 build_gradle 中添加下面的内容
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\framework.jar')
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\framework.jar')
}
}
具体修改内容如图所示
然后点击右上角的 sync now
再次构建. 构建完之后可以看到 framework.jar
已经是可以打开的状态. 同时自动为我们创建了 My_Application.app.imx
文件, 现在需要修改编译顺序, 将默认的sdk 放到最后面, 这样就会优先使用我们的 framework.jar
中的内容了.
这里的修改请参考 如何访问 android系统hide的类或接口, 到这里 Android studio 的环境就搭建完成了, 终于可以开始 app 的编写了.
这一步就比较简单了, 修改文件
MyApplication\app\src\main\java\com\example\myapplication\MainActivity.java
修改内容如下
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.app.HelloManager;
import android.content.Context;
import android.util.Slog;
public class MainActivity extends AppCompatActivity {
private HelloManager mHelloManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 通过 HELLO_SERVICE 这个静态变量获取到 HelloManager
mHelloManager = (HelloManager)getSystemService(Context.HELLO_SERVICE);
mHelloManager.setVal("Hello"); // 调用 setVal 方法
// 调用 getVal方法并打印 log
Slog.i("HelloServiceTest", "HelloService TEST getVal = "+mHelloManager.getVal());
}
}
修改完之后点击运行, 如下图所示.
同步 adb shell 之后 logcat 查看 log 如下, 系统服务接口调佣成功 ∧_∧
01-26 02:27:10.359 2251 2251 I SystemServiceRegistry: registerService HELLO_SERVICE b = android.os.BinderProxy@48b7bd8
01-26 02:27:10.360 2251 2251 I SystemServiceRegistry: registerService HELLO_SERVICE service = android.os.IHelloService$Stub$Proxy@2fbb31
01-26 02:27:10.360 2251 2251 E HelloManager: HelloManager setVal
01-26 02:27:10.361 434 1429 I HelloService: setVal value = Hello
01-26 02:27:10.362 2251 2251 E HelloManager: HelloManager getVal
01-26 02:27:10.362 434 1429 I HelloService: getVal
01-26 02:27:10.363 2251 2251 I HelloServiceTest: HelloService TEST getVal = getVal