android 4.2 系統以後的飛航模式

hrklzwzj發表於2016-07-18

專案中遇到了要控制飛航模式的功能,鑽研了幾天,終於解決。

解決過程中最大的問題是: android 4.2 之後 系統不予許第三方軟體去設定飛航模式,除非你的app是系統應用,得到了root許可權。  蛋疼~~

  網上大多數解決過程是 : 原文 http://blog.sina.com.cn/s/blog_69b5d2a50101fqze.html

   //獲取當前的飛航模式狀態  需要根據不同的Android版本進行修改<wbr><wbr><wbr>

  @SuppressWarnings("deprecation")<wbr>
  public boolean isAirplaneModeOn() <wbr><wbr>
  {<wbr>
  //4.2以下<wbr>
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) <wbr><wbr><wbr><wbr>
     {<wbr><wbr><wbr>
         return Settings.System.getInt(getContentResolver(), <wbr><wbr><wbr><wbr><wbr><wbr>
                 Settings.System.AIRPLANE_MODE_ON, 0) != 0;          <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>
     <wbr><wbr><wbr><wbr>
     else //4.2或4.2以上<wbr><wbr><wbr>
     {<wbr><wbr><wbr>
         return Settings.Global.getInt(getContentResolver(), <wbr><wbr><wbr><wbr><wbr><wbr>
                 Settings.Global.AIRPLANE_MODE_ON, 0) != 0;<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>
     }   <wbr><wbr><wbr><wbr><wbr>
  }<wbr>
 <wbr>
   //設定飛航模式<wbr><wbr>
  @SuppressWarnings("deprecation")<wbr>
  public void setAirplaneModeOn(boolean isEnable) <wbr><wbr>
  {  <wbr><wbr>
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) <wbr><wbr>
     {<wbr><wbr><wbr>
  Settings.System.putInt(getContentResolver(),  <wbr><wbr>
                          Settings.System.AIRPLANE_MODE_ON,isEnable ? 1:0);  <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>
     }<wbr><wbr><wbr>
  else //4.2或4.2以上 <wbr><wbr>
     {<wbr><wbr><wbr>
  Settings.Global.putInt(getContentResolver(), Global.AIRPLANE_MODE_ON, isEnable? 1 : 0);  <wbr><wbr>
     }  <wbr><wbr><wbr><wbr>
  Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);  <wbr><wbr>
  intent.putExtra("state", isEnable);  <wbr><wbr>
  sendBroadcast(intent); <wbr><wbr>
  }  <wbr><wbr>
   需要注意的是,在4.2上其實App是沒有許可權修改Setting.Global的,解決辦法是把你的App放到系統的system/app目錄下,然後install。這樣一來,App成為system app,可以獲得寫Setting.Global的許可權。<wbr><wbr>
 
 
   看看還需要把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

 

 

 

 

相關文章