項目中遇到了要控制飛行模式的功能,鑽研了幾天,終於解決。
解決過程中最大的問題是: android 4.2 之後 系統不予許第三方軟件去設置飛行模式,除非你的app是系統應用,得到了root權限。 蛋疼~~
網上大多數解決過程是 : 原文 http://blog.sina.com.cn/s/blog_69b5d2a50101fqze.html
這是方法,添加到你的應用程序中即可,比較簡陋,呵呵!
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才能生效。
下面是我寫的小程序的界面:
使用方法如下:
- 分別設定好需要開啓、關閉飛行模式的時間,默認情況下爲凌晨12點30分開啓飛行模式,早上7點關閉飛行模式。然後打開當前狀態的按鈕即可,打開後會提示下次切換飛行模式的時間。
- 設定的時間到之後,App會自動嘗試去啓用飛行模式狀態,如上圖第二副圖所示,當然得允許了(最好添加到信任程序列表,不然每次彈框)。另外,設定的時間到之後,有可能你還正在使用手機而不想馬上切換飛行模式,App會給你5s的時間考慮,5秒之後你沒有操作,app就會自動啓用飛行模式了。當然你取消之後,這次就不會切換了,不過當你通過按手機返回鍵(Home鍵不會)或者殺掉這個進程再重新啓動這個App的時候,會根據時間設定滿足規則則自動切換。
- 切換”關閉”狀態即取消設定功能,若當前手機正處於飛行模式狀態,也會切換爲正常狀態。
注意:針對Android4.2及其以上的版本,手機需要ROOT才OK,且建議添加到信任程序列表。4.2之前的版本是木有問題的。
歡迎有興趣的同學下載1
下載2試用,有建議/意見歡迎留言反饋~
TODO:
- Android 各個版本UI風格的統一
- 增加多個時間段的設置,支持晚上睡覺和中午睡覺都轉飛行模式,既省電又防打擾
- 自己寫着瞎玩,應該有不少Bug