編輯:關於Android編程
前陣子工作上遇到一些關於Android系統關機或重啟的系統修改,於是,做了一些嘗試,也搜集了一下資料,現在整理一下,做一些總結,方便學習或者日後工作的需要。
默認的SDK並沒有提供應用開發者直接的Android系統關機或重啟的API接口,一般來講,實現Android系統的關機或重啟,需要較高的權限(系統權限甚至Root權限)。所以,在一般的APP中,如果想要實現關機或重啟功能,要麼是在App中聲明系統權限,要麼是通過某種“間接”的方式,比如廣播或反射,來間接實現系統關機或重啟。再者,就是放在源碼環境中進行編譯,這樣做有一個好處,就是可以直接調用Android中不公開的API,這是Eclipse+SDK沒法達到的效果。下面是我自己嘗試的幾種方式:
一. 發送廣播方式
Broadcast是Android的四大基本組件之一,也就是我們常說的廣播。Android系統本身就包含了許多廣播,時時刻刻在監聽著系統中注冊的每一個廣播並隨時准備響應操作。其中,就有關於關機或重啟的廣播:Intent.ACTION_REQUEST_SHUTDOWN和Intent.ACTION_REBOOT,通過發送這兩個廣播,Android就能自動接收廣播,並響應關機或重啟的操作。ACTION_REQUEST和ACTION_REBOOT是Intent.java是聲明的兩個字符串常量
public static final String ACTION_REBOOT = "android.intent.action.REBOOT"; public static final String ACTION_REQUEST_SHUTDOWN = "android.intent.action.ACTION_REQUEST_SHUTDOWN";
//廣播方式關機重啟
case R.id.shutdown_btn1:
Log.v(TAG, "broadcast->shutdown");
Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
//其中false換成true,會彈出是否關機的確認窗口
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
break;
case R.id.reboot_btn1:
Log.v(TAG, "broadcast->reboot");
Intent intent2 = new Intent(Intent.ACTION_REBOOT);
intent2.putExtra("nowait", 1);
intent2.putExtra("interval", 1);
intent2.putExtra("window", 0);
sendBroadcast(intent2);
break;需要注意的幾點是:
第一,如前面所說,需要將APP提升至系統權限,具體做法是在AndroidMenifest.xml中添加如下代碼
android:sharedUserId="android.uid.system"
第四,由於需要在源碼中編譯項目,所以需要為項目編寫mk文件,在項目根目錄下添加Android.mk文件,內容如下所示:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_PACKAGE_NAME := PowerActionDemo LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE)最後,將編譯生成的apk文件,通過adb push到機器上就可以驗證功能了。
二. 通過init.rc啟動系統服務來運行sh文件
Android啟動文件系統後調用的會調用第一個應用程序是/init,此文件一個很重要的內容就是解析了init.rc和init.xxx.rc,然後執行解析出來的任務。而init.rc,可以在系統的初始化過程中進行一些簡單的初始化操作。利用這一點,可以編寫簡單的關機或重啟的sh腳本文件,通過系統init解析,執行相應的關機或重啟操作。
1.首先,編寫關機和重啟的sh腳本。比如,新建
重啟腳本 system_reboot.sh,內容如下:
#!/system/bin/sh reboot關機腳本 system_shutdown.sh
#!/system/bin/sh reboot -p
2. 編寫Android.mk編譯腳本,目的是在源碼編譯的時候,將這兩個sh文件一起編譯到/system/bin目錄下
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PREBUILT_EXECUTABLES := system_shutdown.sh system_reboot.sh LOCAL_MODULE_TAGS := optional include $(BUILD_MULTI_PREBUILT)
service system_shutdown /system/bin/system_shutdown.sh
oneshot
disabled
service system_reboot /system/bin/system_reboot.sh
oneshot
disableddisabled 表示禁用服務,此服務開機時不會自動啟動,但是可以在應用程序中手動啟動它。
4.新建一個目錄,比如poweraction, 將以上的Android.mk , system_shutdown.sh, system_reboot.sh放在這個目錄下,然後將poweraction這個目錄拷貝到Android系統中,比如device路徑下面。然後,編譯Android源碼,源碼編譯完成後, 查看生成的out/.../system/bin下面是不是包含system_shutdown.sh, system_reboot.sh兩個sh文件,如果有,則說明編譯成功。
5.最後,啟動系統服務,進行關機或重啟。
//啟動系統服務進行關機或重啟
case R.id.shutdown_btn2:
Log.v(TAG, "system service->shutdown");
SystemProperties.set("ctl.start", "system_shutdwon");
break;
case R.id.reboot_btn2:
Log.v(TAG, "system service->reboot");
SystemProperties.set("ctl.start", "system_reboot");
break; 三. Runtime調用Linux-shell
我們知道,Runtime這個Java類是可以用來調用並執行shell命令的,而Android虛擬機是支持Linux-shell語言的,基於這一點,可以利用Runtime來執行 關機或重啟的shell命令,這一點和上面介紹的方式二原理上大致相同。功能代碼如下:
//Runtime執行linux-shell
case R.id.shutdown_btn3:
try{
Log.v(TAG, "root Runtime->shutdown");
//Process proc =Runtime.getRuntime().exec(new String[]{"su","-c","shutdown"}); //關機
Process proc =Runtime.getRuntime().exec(new String[]{"su","-c","reboot -p"}); //關機
proc.waitFor();
}catch(Exception e){
e.printStackTrace();
}
break;
case R.id.reboot_btn3:
try {
Log.v(TAG, "root Runtime->reboot");
Process proc =Runtime.getRuntime().exec(new String[]{"su","-c","reboot "}); //關機
proc.waitFor();
}catch (Exception ex){
ex.printStackTrace();
}
break; Runtime.getRuntime().exec(new String[]{"su","-c","shutdown"})Runtime.getRuntime().exec(new String[]{"su","-c","reboot -p"});四 . PowerManager reboot以及反射調用PowerManagerService shutdown
1. PowerManager提供了reboot等接口,因此,利用PowerManager實現重啟,就比較簡單。
PowerManager pManager=(PowerManager) getSystemService(Context.POWER_SERVICE); //重啟到fastboot模式
pManager.reboot(""); framework/base/core/java/android/os/IPowerManage.aidl
try {
//獲得ServiceManager類
Class> ServiceManager = Class
.forName("android.os.ServiceManager");
//獲得ServiceManager的getService方法
Method getService = ServiceManager.getMethod("getService", java.lang.String.class);
//調用getService獲取RemoteService
Object oRemoteService = getService.invoke(null,Context.POWER_SERVICE);
//獲得IPowerManager.Stub類
Class> cStub = Class
.forName("android.os.IPowerManager$Stub");
//獲得asInterface方法
Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);
//調用asInterface方法獲取IPowerManager對象
Object oIPowerManager = asInterface.invoke(null, oRemoteService);
//獲得shutdown()方法
Method shutdown = oIPowerManager.getClass().getMethod("shutdown",boolean.class,boolean.class);
//調用shutdown()方法
shutdown.invoke(oIPowerManager,false,true);
} catch (Exception e) {
Log.e(TAG, e.toString(), e);
}
快速集成android實現listview的字母A-Z排序,界面側邊字母索引
Android手機字母A-Z排序側邊索引是非常常見的功能,在此提供快速集成框架.教你用Android studio工具一分鐘搞定這個效果.實現效果:以及點擊F跳轉效果&n
Android 自定義View UC下拉刷新效果(二)
啦啦啦,這是山寨UC浏覽器的下拉刷新效果的第二篇,第一篇請移步Android 自定義View UC下拉刷新效果(一)我們看圖說話:主要工作1.下拉刷新的圓形向回首頁的圓形
Android_自定義雙向SeekBar
目標:雙向拖動的自定義View國際慣例先預覽後實現實現步驟自定義屬性的抽取 view尺寸的計算 相關內容的繪制(文字,原點,背景進度條,當前進度條等等) 處理滑動事件大體
android ActionBar用法詳解
一、ActionBar介紹ActionBar是位於Activity頂部,用於顯示Activity的圖標,標題,以及菜單的。可用於導航等功能,廣泛應用於View的交互。Ac