android 4.2 系统以后的飞行模式

项目中遇到了要控制飞行模式的功能,钻研了几天,终于解决。

解决过程中最大的问题是: android 4.2 之后 系统不予许第三方软件去设置飞行模式,除非你的app是系统应用,得到了root权限。  蛋疼~~

  网上大多数解决过程是 : 原文 http://blog.sina.com.cn/s/blog_69b5d2a50101fqze.html

   //获取当前的飞行模式状态  需要根据不同的Android版本进行修改

  @SuppressWarnings("deprecation")
  public boolean isAirplaneModeOn() 
  {
  //4.2以下
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) 
     {
         return Settings.System.getInt(getContentResolver(), 
                 Settings.System.AIRPLANE_MODE_ON, 0) != 0;          
     
     else //4.2或4.2以上
     {
         return Settings.Global.getInt(getContentResolver(), 
                 Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
     }   
  }
 
   //设置飞行模式
  @SuppressWarnings("deprecation")
  public void setAirplaneModeOn(boolean isEnable) 
  {  
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) 
     {
  Settings.System.putInt(getContentResolver(),  
                          Settings.System.AIRPLANE_MODE_ON,isEnable ? 1:0);  
     }
  else //4.2或4.2以上 
     {
  Settings.Global.putInt(getContentResolver(), Global.AIRPLANE_MODE_ON, isEnable? 1 : 0);  
     }  
  Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);  
  intent.putExtra("state", isEnable);  
  sendBroadcast(intent); 
  }  
   需要注意的是,在4.2上其实App是没有权限修改Setting.Global的,解决办法是把你的App放到系统的system/app目录下,然后install。这样一来,App成为system app,可以获得写Setting.Global的权限。
 
 
   看看还需要把app变成系统应用,好像很麻烦,我是没有去研究把它变成系统应用。
  哎!网上去搜吧!  有人搜到stackoverflow上用adb shell 来解决:那 shell怎么去调用呢?
 
adb在终端执行的命令:
 
    第一种方法:
          
这是方法,添加到你的应用程序中即可,比较简陋,呵呵!
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才能生效。

下面是我写的小程序的界面:

android自动切换飞行模式

使用方法如下:

  1. 分别设定好需要开启、关闭飞行模式的时间,默认情况下为凌晨12点30分开启飞行模式,早上7点关闭飞行模式。然后打开当前状态的按钮即可,打开后会提示下次切换飞行模式的时间。
  2. 设定的时间到之后,App会自动尝试去启用飞行模式状态,如上图第二副图所示,当然得允许了(最好添加到信任程序列表,不然每次弹框)。另外,设定的时间到之后,有可能你还正在使用手机而不想马上切换飞行模式,App会给你5s的时间考虑,5秒之后你没有操作,app就会自动启用飞行模式了。当然你取消之后,这次就不会切换了,不过当你通过按手机返回键(Home键不会)或者杀掉这个进程再重新启动这个App的时候,会根据时间设定满足规则则自动切换。
  3. 切换”关闭”状态即取消设定功能,若当前手机正处于飞行模式状态,也会切换为正常状态。

注意:针对Android4.2及其以上的版本,手机需要ROOT才OK,且建议添加到信任程序列表。4.2之前的版本是木有问题的。

欢迎有兴趣的同学下载1 下载2试用,有建议/意见欢迎留言反馈~

TODO:

  1. Android 各个版本UI风格的统一
  2. 增加多个时间段的设置,支持晚上睡觉和中午睡觉都转飞行模式,既省电又防打扰
  3. 自己写着瞎玩,应该有不少Bug

 

 

 

 

展开阅读全文

没有更多推荐了,返回首页