編輯:關於Android編程
Android 長按電源鍵關機整個流程小學習
最近研究了一下android關機跟重新啟動功能,看了一些長按電源鍵到彈出關機對話框,到真正關機的一系列處理過程。
首先還是來看看這個長按電源鍵都干了些什麼吧?一般來說,電源鍵都是接到PMU上的,PMU來判斷是長按還短按,當有按鍵消息產生的時候,系統會有中斷,然後去讀PMU的狀態就可以知道是什麼了。筆者以全志平台的AXP209小議一下,先貼上關鍵代碼:
static int axp_battery_event(struct notifier_block *nb, unsigned long event, void *data) { struct axp_charger *charger = container_of(nb, struct axp_charger, nb); uint8_t w[9]; w[0] = (uint8_t) ((event) & 0xFF); w[1] = POWER20_INTSTS2; w[2] = (uint8_t) ((event >> 8) & 0xFF); w[3] = POWER20_INTSTS3; w[4] = (uint8_t) ((event >> 16) & 0xFF); w[5] = POWER20_INTSTS4; w[6] = (uint8_t) ((event >> 24) & 0xFF); w[7] = POWER20_INTSTS5; w[8] = (uint8_t) (((uint64_t) event >> 32) & 0xFF); if(event & (AXP20_IRQ_BATIN|AXP20_IRQ_BATRE)) { axp_capchange(charger); } if(event & (AXP20_IRQ_ACIN|AXP20_IRQ_USBIN|AXP20_IRQ_ACOV|AXP20_IRQ_USBOV|AXP20_IRQ_CHAOV |AXP20_IRQ_CHAST|AXP20_IRQ_TEMOV|AXP20_IRQ_TEMLO)) { axp_change(charger); } if(event & (AXP20_IRQ_ACRE|AXP20_IRQ_USBRE)) { axp_change(charger); } if(event & AXP20_IRQ_PEKLO) { axp_presslong(charger); } if(event & AXP20_IRQ_PEKSH) { axp_pressshort(charger); } DBG_PSY_MSG("event = 0x%x\n",(int) event); axp_writes(charger->master,POWER20_INTSTS1,9,w); return 0; }
短按跟長按具體也就是上報的延時區別,如下:
static void axp_presslong(struct axp_charger *charger) { DBG_PSY_MSG("press long\n"); input_report_key(powerkeydev, KEY_POWER, 1); input_sync(powerkeydev); ssleep(2); DBG_PSY_MSG("press long up\n"); input_report_key(powerkeydev, KEY_POWER, 0); input_sync(powerkeydev); } static void axp_pressshort(struct axp_charger *charger) { DBG_PSY_MSG("press short\n"); input_report_key(powerkeydev, KEY_POWER, 1); input_sync(powerkeydev); msleep(100); input_report_key(powerkeydev, KEY_POWER, 0); input_sync(powerkeydev); }
在inputmanager裡面再解析出是長按還是短按,來做相應處理。如果是長按,就彈出對話框,在彈出對話框之前,有幾次傳遞,還是activitymanger跟Windowsmanagerservice做宏觀調控,最終把消息傳到苦逼的ShutdownThread,不過ShutdownThread也不難弄。/*****************************************************************************************************/
聲明:本博內容均由http://blog.csdn.net/sundesheng125原創,轉載請注明出處,謝謝!
/*****************************************************************************************************/
首先來看一下,在ShutdownThread裡面有一個CloseDialogReceiver來關注Intent.ACTION_CLOSE_SYSTEM_DIALOGS,它收到這個消息就會關閉這個對話框。對話框怎麼起來的呢?請看下面的源碼:
if (confirm) { final CloseDialogReceiver closer = new CloseDialogReceiver(context); final AlertDialog dialog = new AlertDialog.Builder(context) .setTitle(com.android.internal.R.string.power_off) .setMessage(resourceId) .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { beginShutdownSequence(context); } }) .setNegativeButton(com.android.internal.R.string.no, null) .create(); closer.dialog = dialog; dialog.setOnDismissListener(closer); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); dialog.show(); } else { beginShutdownSequence(context); }
其實就是一個AlertDialog,也沒什麼新鮮的,只是在setPositiveButton的時候注冊了clicklistener來監聽你是否按下了,按下了就直接執行beginShutdownSequence。在beginShutdownSequence還會彈出一個進度的對話框,代碼如下:
ProgressDialog pd = new ProgressDialog(context); pd.setTitle(context.getText(com.android.internal.R.string.power_off)); pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); pd.setIndeterminate(true); pd.setCancelable(false); pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); pd.show();
在裡面還會調用兩個非常重要的Power.shutdown()跟Power.reboot(reason),看你是重啟還是關機了。
/** * Low-level function turn the device off immediately, without trying * to be clean. Most people should use * {@link android.internal.app.ShutdownThread} for a clean shutdown. * * @deprecated * @hide */ @Deprecated public static native void shutdown(); /** * Reboot the device. * @param reason code to pass to the kernel (e.g. "recovery"), or null. * * @throws IOException if reboot fails for some reason (eg, lack of * permission) */ public static void reboot(String reason) throws IOException { rebootNative(reason); } private static native void rebootNative(String reason) throws IOException ;
再往下跟,
static void android_os_Power_shutdown(JNIEnv *env, jobject clazz) { android_reboot(ANDROID_RB_POWEROFF, 0, 0); } extern int go_recovery(void); static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason) { if (reason == NULL) { android_reboot(ANDROID_RB_RESTART, 0, 0); } else { const char *chars = env->GetStringUTFChars(reason, NULL); //android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars); go_recovery(); android_reboot(ANDROID_RB_RESTART, 0, 0); env->ReleaseStringUTFChars(reason, chars); // In case it fails. } jniThrowIOException(env, errno); }
所以,整個流程都是好的,學習理了一下流程,大部分都是源碼,把它搞清楚也是有好處的。
最近做的項目中需要實現斷點下載,即用戶一次下載可以分多次進行,下載過程可以中斷,在目前大多數的帶離線緩存的軟件都是需要實現這一功能。本文闡述了通過sqlite3簡單實現了
指紋識別已經成為智能手機新一代必備功能,指紋識別讓你的手指有了更多用途。除了免輸密碼解鎖,它還有更多便捷功能,例如:指紋支付購物,查看私密文件等
先來看下要實現效果圖:查閱資料後,發現網上大部分都是用這種方法實現的:多寫一個和需要懸浮的部分一模一樣的layout,先把浮動區域的可見性設置為gone。當浮動區域滑動到
本篇博客主要講解怎樣自定義一個circleIndicator控件?下一遍博客主要講解怎樣更改ViewPager切換的效果, 預計明天晚上之前更新。效果圖如下1)首先我們先