2.1Android关机流程
Android关机流程的介绍网上很多,现在摘抄一段如下:
仔细按照上面说的流程跟下去,确实是这样的,只不过根据产品的不同,会有一定的修改,例如产品是平板电脑,就会比手机少很多废话对话框,如果是智能电视,则又会有不同,
对于这个任务来说,比较重要的ShutdownThread.java这个文件,这个文件启动了关机的对话框,关机对话框效果如图:
PhoneWindowManager中调用ShutdownThread的代码如下:
传入第一个参数不解释,第二个参数是是否显示对话框,true就是显示。
2.2应用中关机的方法
凭借网络这个好老师,我找到了好几种实现关机的方法,一是通过向控制台写shutdown命令完成,Android是建立在Linux基础上的,所以这种方法需要Root。
二是启动ShutdownThread中的对话框,PhoneWindowManager直接通过一句 ShutdownThread.shutdown(mContext, true); 就启动了,后面我也试过这种方法,确实可以启动,但是点击确定却一直关不了机。所以靠谱的方法还是通过Intent启动。方法如下:
这上面的一些Flag值AndroidSDK中并没有公开,所以工程要放在Android源码中才能编译通过,除此之外还需要设置系统权限,需要通过修改AndroidManfast.xml文件实现。
2.3Appwidget的框架
个人感觉AppWidget像是嵌入launcher中的View,和AppWidget本身Activity的不是运行在同一个进程中,所以控制Appwidget都需要用RemoteViews控制。
桌面上有多个不同的AppWidget,如何得知哪一个被激活呢,这主要通过广播完成,广播发出的是在AndroidManfast.xml中定义好的android:name,接收时需要在OnReceive()方法中进行判断。
AndroidMainfast.xml摘录如下:
Appwidget的处理片段如下:
Android关机流程的介绍网上很多,现在摘抄一段如下:
点击(此处)折叠或打开
- 关机动作从按键触发中断,linux kernel层给android framework层返回按键事件进入 framework层,再从 framework层到kernel层执行kernel层关机任务。
- 长按键对应的handler代码:
- frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java
- Runnable mPowerLongPress;
- private final Runnable mPowerLongPress = new Runnable() {
- public void run() {
- if (!mPowerKeyHandled) {
- mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- showGlobalActionsDialog();
- }
- }
- };
- mPowerLongPress 启动关机对话框
- (frameworks/policies/base/phone/com/android/internal/policy/impl/GlobalActions.java)
- 如果我们选择Power OFF’,会调用 ShutdownThread.shutdown. 启动关机线程执行关机动作。
- frameworks/base/core/java/com/android/internal/app/ShutdownThread.java
- 真正关机 流程:
- (1)广播全局事件, ACTION_SHUTDOWN Intent
- (2)shutdown ActivityManager 服务
- (3) 停止蓝牙服务
- (4) 停止 电话服务 (radio phone service)
- (5)停止mount 服务
- (6) 调用 Power.shutdown() 进入native 层
- frameworks/base/core/java/android/os/Power.java
- power的native实现代码:
- frameworks/base/core/jni/android_os_Power.cpp
- static void android_os_Power_shutdown(JNIEnv *env, jobject clazz)
- {
- sync();
- #ifdef HAVE_ANDROID_OS
- reboot(RB_POWER_OFF);
- #endif
- }
- sync, reboot 为linux系统调用,进入linux内核关机流程。
- 完毕。
PhoneWindowManager中调用ShutdownThread的代码如下:
点击(此处)折叠或打开
- mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- ShutdownThread.shutdown(mContext, true);
2.2应用中关机的方法
凭借网络这个好老师,我找到了好几种实现关机的方法,一是通过向控制台写shutdown命令完成,Android是建立在Linux基础上的,所以这种方法需要Root。
二是启动ShutdownThread中的对话框,PhoneWindowManager直接通过一句 ShutdownThread.shutdown(mContext, true); 就启动了,后面我也试过这种方法,确实可以启动,但是点击确定却一直关不了机。所以靠谱的方法还是通过Intent启动。方法如下:
点击(此处)折叠或打开
- Intent shutdown = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
- shutdown.putExtra(Intent.EXTRA_KEY_CONFIRM, true);
- shutdown.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(shutdown);
2.3Appwidget的框架
个人感觉AppWidget像是嵌入launcher中的View,和AppWidget本身Activity的不是运行在同一个进程中,所以控制Appwidget都需要用RemoteViews控制。
桌面上有多个不同的AppWidget,如何得知哪一个被激活呢,这主要通过广播完成,广播发出的是在AndroidManfast.xml中定义好的android:name,接收时需要在OnReceive()方法中进行判断。
AndroidMainfast.xml摘录如下:
点击(此处)折叠或打开
- <receiver android:name="AppWidget">
- <intent-filter>
- <action
- android:name="android.appwidget.action.APPWIDGET_UPDATE">
- </action>
- </intent-filter>
- <meta-data android:name="android.appwidget.provider"
- android:resource="@xml/appwidget01" />
- <intent-filter>
- <action android:name="com.android.shutdownapp"></action>
- </intent-filter>
- </receiver>
点击(此处)折叠或打开
- @Override
- public void onReceive(Context context, Intent intent)
- {
- if (intent.getAction().equals(broadCastString))
- {
- RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.appwidgetlayout);
- remoteViews.setTextViewText(R.id.btnSend, "shutdown");
- AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
- ComponentName componentName = new ComponentName(context,AppWidget.class);
- appWidgetManager.updateAppWidget(componentName, remoteViews);
- }
- super.onReceive(context, intent);
- }