Android編程實(shí)現(xiàn)系統(tǒng)重啟與關(guān)機(jī)的方法
本文實(shí)例講述了Android編程實(shí)現(xiàn)系統(tǒng)重啟與關(guān)機(jī)的方法。分享給大家供大家參考,具體如下:
最近在做個(gè)東西,巧合碰到了sharedUserId 的問(wèn)題,所以收集了一些資料,存存檔備份。
安裝在設(shè)備中的每一個(gè)apk文件,Android 給每個(gè) APK 進(jìn)程分配一個(gè)單獨(dú)的用戶空間,其 manifest 中的 userid 就是對(duì)應(yīng)一個(gè) Linux 用戶都會(huì)被分配到一個(gè)屬于自己的統(tǒng)一的 Linux 用戶 ID,并且為它創(chuàng)建一個(gè)沙箱,以防止影響其他應(yīng)用程序(或者其他應(yīng)用程序影響它)。
用戶 ID 在應(yīng)用程序安裝到設(shè)備中時(shí)被分配,并且在這個(gè)設(shè)備中保持它的永久性。
通過(guò) Shared User id 擁有同一個(gè)User id的多個(gè)APK可以配置成運(yùn)行在同一個(gè)進(jìn)程中.所以默認(rèn)就是可以互相訪問(wèn)任意數(shù)據(jù). 也可以配置成運(yùn)行成不同的進(jìn)程,同時(shí)可以訪問(wèn)其他APK的數(shù)據(jù)目錄下的數(shù)據(jù)庫(kù)和文件.就像訪問(wèn)本程序的數(shù)據(jù)一樣.
對(duì)于一個(gè) APK 來(lái)說(shuō),如果要使用某個(gè)共享 UID 的話,必須做三步:
1、在 Manifest 節(jié)點(diǎn)中增加 android:sharedUserId 屬性。
2、在 Android.mk 中增加 LOCAL_CERTIFICATE 的定義。
如果增加了上面的屬性但沒(méi)有定義與之對(duì)應(yīng)的 LOCAL_CERTIFICATE 的話,APK是安裝不上去的。
提示錯(cuò)誤是:
Package com.test.MyTest has no signatures that match those in shared user android.uid.system; ignoring!
也就是說(shuō),僅有相同簽名和相同 sharedUserID 標(biāo)簽的兩個(gè)應(yīng)用程序簽名都會(huì)被分配相同的用戶ID。
例如所有和 media/download 相關(guān)的 APK 都使用 android.media 作為 sharedUserId 的話,那么它們必須有相同的簽名 media。
3、把 APK 的源碼放到 packages/apps/ 目錄下,用 mm 進(jìn)行編譯。
舉例說(shuō)明一下。
系統(tǒng)中所有使用android.uid.system作為共享UID的APK,都會(huì)首先在manifest節(jié)點(diǎn)中增加:
android:sharedUserId="android.uid.system"
然后在 Android.mk 中增加
LOCAL_CERTIFICATE := platform
可以參見(jiàn)Settings等。
系統(tǒng)中所有使用 android.uid.shared 作為共享 UID 的 APK,都會(huì)在 manifest 節(jié)點(diǎn)中增加
android:sharedUserId="android.uid.shared"
然后在 Android.mk 中增加
LOCAL_CERTIFICATE := shared
可以參見(jiàn)Launcher等
系統(tǒng)中所有使用 android.media 作為共享 UID 的 APK,都會(huì)在 manifest 節(jié)點(diǎn)中增加
android:sharedUserId="android.media"
然后在 Android.mk 中增加
LOCAL_CERTIFICATE := media
可以參見(jiàn)Gallery等。
另外,應(yīng)用創(chuàng)建的任何文件都會(huì)被賦予應(yīng)用的用戶標(biāo)識(shí),并且正常情況下不能被其他包訪問(wèn)。
當(dāng)通過(guò) getSharedPreferences(String,int)、openFileOutput(String、int)或者 openOrCreate Database(String、int、SQLiteDatabase.CursorFactory)
創(chuàng)建一個(gè)新文件時(shí),開(kāi)發(fā)者可以同時(shí)或分別使用MODE_WORLD_READABLE 和MODE_WORLD_RITEABLE 標(biāo)志允許其他包讀/寫此文件。當(dāng)設(shè)置了這些標(biāo)志后,這個(gè)文件仍然屬于自己的應(yīng)用程序,但是它的全局讀/寫和讀/寫權(quán)限已經(jīng)設(shè)置,所以其他任何應(yīng)用程序可以看到它。
關(guān)于簽名:
build/target/product/security 目錄中有四組默認(rèn)簽名供 Android.mk 在編譯APK使用:
1、testkey: 普通 APK,默認(rèn)情況下使用。
2、platform:該 APK 完成一些系統(tǒng)的核心功能。經(jīng)過(guò)對(duì)系統(tǒng)中存在的文件夾的訪問(wèn)測(cè)試,這種方式編譯出來(lái)的 APK 所在進(jìn)程的 UID 為 system。
3、shared: 該APK需要和home/contacts進(jìn)程共享數(shù)據(jù)。
4、media:該APK是media/download系統(tǒng)中的一環(huán)。
應(yīng)用程序的 Android.mk 中有一個(gè) LOCAL_CERTIFICATE 字段,由它指定用哪個(gè) key 簽名,未指定的默認(rèn)用 testkey
在應(yīng)用層如何通過(guò)代碼實(shí)現(xiàn) Android 系統(tǒng)的重啟,分享給大家。
這篇文章是在 android 系統(tǒng)開(kāi)發(fā)的基礎(chǔ)之上進(jìn)行實(shí)踐的,所以如果你是純粹的 app 開(kāi)發(fā),可能要讓你失望了。
該代碼在真機(jī)上測(cè)試成功,在模擬器上面測(cè)試失敗。
在 linux 下面,重啟 pc,非 root 用戶需要執(zhí)行 sudo reboot,所以在 android 下重啟機(jī)器也需要一定的權(quán)限。
應(yīng)用程序界面:
1. 新建一個(gè) android 工程 reboot
2. 編寫 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 := reboot LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE) # Use the folloing include to make our test apk. include $(call all-makefiles-under,$(LOCAL_PATH))
具體含義可自行查閱資料。注意:
LOCAL_CERTIFICATE := platform
3. 編寫補(bǔ)充 AndroidMenifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mark.zhang" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:sharedUserId="android.uid.system" > <activity android:label="@string/app_name" android:name=".RebootActivity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
注意:
android:sharedUserId="android.uid.system"
4. 編寫邏輯代碼 RebootActivity.java
package mark.zhang; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class RebootActivity extends Activity { // 是否顯示關(guān)機(jī)確認(rèn)的對(duì)話框 // false 不顯示確認(rèn)關(guān)機(jī)的對(duì)話框,直接關(guān)機(jī) // true 顯示確認(rèn)關(guān)機(jī)的對(duì)話框,讓用戶選擇是否確認(rèn)關(guān)機(jī) public static final boolean showShutdownDialog = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } /** * 發(fā)送廣播. * * @param view */ public void onReboot(View view) { Intent reboot = new Intent(Intent.ACTION_REBOOT); reboot.putExtra("nowait", 1); reboot.putExtra("interval", 1); reboot.putExtra("window", 0); sendBroadcast(reboot); } /** * 啟動(dòng) Activity. * * @param view */ public void onShutdown(View view) { public void onShutdown(View view) { Intent shutdown = new Intent(Intent.ACTION_REQUEST_SHUTDOWN); shutdown.putExtra(Intent.EXTRA_KEY_CONFIRM, showShutdownDialog); shutdown.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(shutdown); } } }
注意:
Intent.ACTION_REQUEST_SHUTDOWN Intent.EXTRA_KEY_CONFIRM
會(huì)報(bào)錯(cuò),這是因?yàn)樵搶傩允?nbsp; {@hide} 的。
不要擔(dān)心放到系統(tǒng)編譯就可以了,注意下面的步驟即可。
5. 將整個(gè)工程放到 android 源碼里面編譯
a. 手動(dòng)復(fù)制 reboot 到 src/packages/app 下面
b. mm -j4 開(kāi)始編譯(可以參考 《Android入門之源碼開(kāi)發(fā)基礎(chǔ)教程》)
如果編譯成功,在 /out/target/product/generic/system/app 目錄下面,會(huì)多一個(gè) reboot.apk 文件。
6. 安裝 apk
該 apk 必須放到 system/app 下面,即 adb push reboot.apk /system/app
思考:
關(guān)機(jī)或者重啟,一個(gè)是發(fā)送廣播,一個(gè)是啟動(dòng) Activity。
通過(guò)查找相應(yīng)的 action 或者 string 資源(如關(guān)機(jī)關(guān)鍵字)就可以找到對(duì)應(yīng)的類。
我們知道,framwork 的 mk 文件、資源文件等都在:
/frameworks/base/core/res、frameworks/base/core/res/res
比如關(guān)機(jī)的那個(gè) Activity 就是 ShutDownActiviy,其又調(diào)用 ShutdownThread.shutdown。
重啟的相關(guān)的類在 WatchDog.java(定義了相關(guān)的量), 其內(nèi)部類 RebootRequestReceiver 是主要代碼。
繼續(xù)追蹤你就會(huì)了解整個(gè)流程了。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android開(kāi)發(fā)入門與進(jìn)階教程》、《Android多媒體操作技巧匯總(音頻,視頻,錄音等)》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android 關(guān)機(jī)彈出選擇菜單的深入解析
- Android開(kāi)發(fā)實(shí)現(xiàn)長(zhǎng)按返回鍵彈出關(guān)機(jī)框功能
- Android實(shí)現(xiàn)關(guān)機(jī)與重啟的幾種方式(推薦)
- Android手機(jī)獲取root權(quán)限并實(shí)現(xiàn)關(guān)機(jī)重啟功能的方法
- Android實(shí)現(xiàn)關(guān)機(jī)重啟的方法分享
- Android系統(tǒng)關(guān)機(jī)的全流程解析
- Android6.0動(dòng)態(tài)申請(qǐng)權(quán)限所遇到的問(wèn)題小結(jié)
- Android獲取設(shè)備隱私 忽略6.0權(quán)限管理
- 談?wù)凙ndroid6.0運(yùn)行時(shí)的權(quán)限處理
- Android6.0 屏幕固定功能詳解
- Android 6.0開(kāi)發(fā)實(shí)現(xiàn)關(guān)機(jī)菜單添加重啟按鈕的方法
相關(guān)文章
Android自定義ViewGroup之WaterfallLayout(二)
這篇文章主要為大家詳細(xì)介紹了Android自定義ViewGroup之WaterfallLayout,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Android動(dòng)畫(huà)學(xué)習(xí)筆記之補(bǔ)間動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了Android動(dòng)畫(huà)學(xué)習(xí)筆記之補(bǔ)間動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12Android中使用ZXing生成二維碼(支持添加Logo圖案)
ZXing是谷歌的一個(gè)開(kāi)源庫(kù),可以用來(lái)生成二維碼、掃描二維碼。接下來(lái)通過(guò)本文給大家介紹Android中使用ZXing生成二維碼(支持添加Logo圖案),需要的朋友參考下2017-01-01Flutter定義tabbar底部導(dǎo)航路由跳轉(zhuǎn)的方法
這篇文章主要為大家詳細(xì)介紹了Flutter定義tabbar底部導(dǎo)航路由跳轉(zhuǎn)的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07Android 使用 RxJava2 實(shí)現(xiàn)倒計(jì)時(shí)功能的示例代碼
本篇文章主要介紹了Android 使用 RxJava2 實(shí)現(xiàn)倒計(jì)時(shí)功能的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Android實(shí)現(xiàn)從本地圖庫(kù)/相機(jī)拍照后裁剪圖片并設(shè)置頭像
玩qq或者是微信的盆友都知道,這些聊天工具里都要設(shè)置頭像,一般情況下大家的解決辦法是從本地圖庫(kù)選擇圖片或是從相機(jī)拍照,然后根據(jù)自己的喜愛(ài)截取圖片,接下來(lái)通過(guò)本文給大家介紹Android實(shí)現(xiàn)從本地圖庫(kù)/相機(jī)拍照后裁剪圖片并設(shè)置頭像,需要的朋友參考下2016-02-02Android View教程之自定義驗(yàn)證碼輸入框效果
這篇文章主要給大家介紹了關(guān)于Android View教程之自定義驗(yàn)證碼輸入框效果的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05