项目中遇到了要控制飞行模式的功能,钻研了几天,终于解决。
解决过程中最大的问题是: android 4.2 之后 系统不予许第三方软件去设置飞行模式,除非你的app是系统应用,得到了root权限。 蛋疼~~
网上大多数解决过程是 : 原文 http://blog.sina.com.cn/s/blog_69b5d2a50101fqze.html
//获取当前的飞行模式状态 需要根据不同的Android版本进行修改
这是方法,添加到你的应用程序中即可,比较简陋,呵呵!
public
void
execShell(String cmd){
try
{
//权限设置
Process p = Runtime.getRuntime().exec(
"su"
);
//获取输出流
OutputStream outputStream = p.getOutputStream();
DataOutputStream dataOutputStream=
new
DataOutputStream(outputStream);
//将命令写入
dataOutputStream.writeBytes(cmd);
//提交命令
dataOutputStream.flush();
//关闭流操作
dataOutputStream.close();
outputStream.close();
}
catch
(Throwable t)
{
t.printStackTrace();
}
}
public
void
execCommand(String command)
throws
IOException {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(command);
try
{
if
(proc.waitFor() !=
0
) {
System.err.println(
"exit value = "
+ proc.exitValue());
}
BufferedReader in =
new
BufferedReader(
new
InputStreamReader(
proc.getInputStream()));
StringBuffer stringBuffer =
new
StringBuffer();
String line =
null
;
while
((line = in.readLine()) !=
null
) {
stringBuffer.append(line+
" "
);
}
System.out.println(stringBuffer.toString());
}
catch
(InterruptedException e) {
System.err.println(e);
}
finally
{
try
{
proc.destroy();
}
catch
(Exception e2) {
}
}
}
开关飞行模式的命令:
//开启飞行模式
settings put global airplane_mode_on 1
am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true
//关闭飞行模式settings put global airplane_mode_on 0
am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false
呵呵 安装apk之前,记得先把你的手机root哟 。
下面给出一片好文章,好学校的就是好:http://www.tanglei.name/blog/android-airplanemode-auto-switcher.html
UPDATE: 代码托管在GitHub上了, 欢迎有兴趣的童鞋加入一起完善。
之前写过一个Android手机根据时间设定自动切换飞行模式的代码,这次换了个屌丝红米手机之后安装后发现用不了。于是决定重新写一个。
整个功能要实现的话思路很清晰,只要改变一下系统配置(System.AIRPLANE_MODE_ON),发送一个通知即可。但发现Android的权限设置没有以前那么开放了。从Android 4.2开始(SDK API 17),设备的这些属性是只读的,官网上说:
Some device settings defined by Settings.System are now read-only. If your app attempts to write changes to settings defined in Settings.System that have moved to Settings.Global, the write operation will silently fail when running on Android 4.2 and higher.
所以对于Android4.2及其以上版本的手机来说就悲剧了~
刚开始在代码里面试图去修改System.AIRPLANE_MODE_ON 的属性,UI上貌似没有什么反映,log看到说缺少android.permission.WRITE_SECURE_SETTINGS 权限,在manifest里面声明,eclipse 又编译不过提示 Permission is only System Apps,说是必须得是系统应用才行。网上也有讨论各种解决方案,有说要写成系统应用,需要一个跟固件一起打包编译或者跟固件有相同的签名才行。同样也有人说通过反射可以实现。第一种方式应该很麻烦,得下某源码包编啊之类的,第二种方案有人说可以尝试下,但具体我也没试~不知道是否靠谱。
后来的后来,还是从网上找到了解决方案,不过device必须得root,不然没办法搞定。原文来自这里,虽然不知道是哪国语言~但代码还是认识。
//开启飞行模式
settings put global airplane_mode_on 1
am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true
//关闭飞行模式
settings put global airplane_mode_on 0
am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false
通过adb shell,输入以上两句命令,可以将切换飞行模式。核心问题解决了~剩下的就是需要通过Java代码去调用shell命令,这个不难~不过得注意需要通过root去调用,另外得防止程序卡死~
再后来在stackoverflow上也有人提到了这个解决方案,并且还给了另外一个解决方案,即通过sqlite去直接改变Android的系统配置。数据库位置在/data/data/com.android.providers.settings/databases/settings.db
sqlite3 /data/data/com.android.providers.settings/databases/settings.db
insert into global values(null, 'airplane_mode_on', 1); //相应的插入0值,即是取消飞行模式
当然上面的数据库修改之后要生效,还是必须得发上面的那个broadcast才能生效。
下面是我写的小程序的界面:
使用方法如下:
注意:针对Android4.2及其以上的版本,手机需要ROOT才OK,且建议添加到信任程序列表。4.2之前的版本是木有问题的。
欢迎有兴趣的同学下载1 下载2试用,有建议/意见欢迎留言反馈~
TODO: