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

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章