
-- 作者 谢恩铭 转载请注明出处
内容简介
- 前言
- 解决
1. 前言
最近, 在 Android 开发中遇到一个问题, 有个 app 需要每次烧写(比如略修改一些代码, 就要重新编译, 再烧录到 Android 手机里)。
这样, 对于测试一些代码的改动就不是很方便了, 比如我要修改 Android 底层 C++ 代码中的两个变量, 这两个都可以取整数值。
其中一个是 echo_delay, 另一个是 filter_length。
我要测试出这两个数值的最佳组合,需要测试很多次,也就是要修改、编译、烧写、启动很多次,这工作量那是相当大呀。
2. 解决
有没有什么办法可以大大减轻工作量呢?必须有!
自己找了一下:
在 Android 开发中,你可以用 USB 线连接 Android 设备和电脑,进入 adb 模式(用 adb shell),然后用各种命令来操作你的手机。
Android 系统有不少属性,例如:
ro.product.model
是对应设备的型号。如果我在 Samsung 的 S5 手机上,它的值是
SM-G900F
这些系统属性是在 /system/build.prop 这个文件中,需要你有 Root 权限才能修改。

我们可以用 cat 命令来打印出 /system/build.prop 这个文件的内容:
cat /system/build.prop

属性很多,我们只截屏了开头的一部分。
可以看到属性中有很多是以 ro 开头的,例如:
ro.product.model
ro.build.id
ro.product.board
等等。
ro 表示 Read Only,是英语「只读」的意思,表示只能读取,不能修改。
当然了,这些 ro 开头的属性也不是不能修改,你可以通过一些方式来修改。修改的后果自负。
你可以自行 Google 搜索,或者参考这篇 StackOverFlow 的文章,或者这篇文章,不过不在本课讨论之列。
adb 的众多命令中有一个命令叫做 setprop,是 set property(设置属性)的简写,用于为系统设置属性的值,就是类似键值对的概念。
setprop 命令还可以用于设置自定义的属性。你可以随便取什么名字的属性,例如 hostname,可以用如下方法来设置它的值:
setprop 属性名称 属性的值
既然有 setprop 命令,Android 也提供了 getprop 命令,用于显示属性的值。
使用方法如下:
getprop 属性名称
用 setprop 设置了设备的属性之后,在 Android 的代码中就可以获取到属性的值。
例如我们来修改系统的一个属性值,名叫 media.enable-commonsource(这个属性值不是以 ro 开头,不是只读,可以修改),它的默认值是 true。我们可以用
setprop media.enable-commonsource false
把它的值改为 false。然后用 getprop 来查看它新的值:
getprop media.enable-commonsource

可以看到,media.enable-commonsource 已经被我们从 true 改成了 false。
用这个原理,我们只要用 setprop 命令修改我们的两个变量的取值,就立即生效了。很方便吧!
首先你可以在 Java 代码中写一个你自己的 readProp 函数,用于根据属性的名称来获取属性的值,可以类似如下:
private int readProp(String prop) {
try {
Process process = Runtime.getRuntime().exec("getprop " + prop);
InputStreamReader ir = new InputStreamReader(process.getInputStream());
BufferedReader input = new BufferedReader(ir);
return Integer.parseInt(input.readLine());
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
}
在你的代码中调用
int delay = readProp("delay");
int filter = readProp("filter");
Log.i(TAG, "Echo_delay = " + delay + ", filter_length = " + filter);
然后把代码编译,烧写到 Android 设备中,再用 setprop 命令开始测试。
例如设置 echo delay:
setprop delay 250
可以用 getprop 命令看看设置的值是否正确:
getprop delay

设置另一个值 filter length:
setprop filter 100
getprop filter

我们在 Logcat 里打印出来的值也可以验证我们的设置:

这样, 你就只要一次烧写, 之后这两个值完全可以通过命令行来实时修改, 岂不快哉~
对于 Android 嵌入式开发来说,这种方法还是非常实用的, 可以大大加快测试和开发速度。
我是谢恩铭,在巴黎奋斗的软件工程师。
热爱生活,喜欢游泳,略懂烹饪。
人生格言:「向着标杆直跑」
网友评论
已经修改。谢谢。
不过这些 ro 开头的属性也不是不能修改,可以通过一些方式来修改。
大家可以自行 Google 搜索,或者参考这篇 StackOverFlow 的文章 https://stackoverflow.com/questions/23758994/change-the-model-in-build-prop ,或者这篇文章 http://www.techgainer.com/change-fake-android-device-model-number-and-brand-name/ ,不过不在本课讨论之列。