【0073】【项目实战】-【手机安全卫士】-【13】窗体小部件布局获取&反编译
1. 效果及编写的思路

【说明】将其拖拽到桌面,可以显示该程序的小窗口布局;

2.文档的参考



【资源文件中的属性】

1 在res/xml/创建文件example_appwidget_info.xml拷贝文档内容 2 3 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 4 android:minWidth="294dp" 5 android:minHeight="72dp"//能被调整的最小宽高,若大于minWidth minHeight 则忽略 6 android:updatePeriodMillis="86400000"//更新周期,毫秒,最短默认半小时 7 android:previewImage="@drawable/preview"//选择部件时 展示的图像,3.0以上使用,默认是ic_launcher 8 android:initialLayout="@layout/example_appwidget"//布局文件 9 android:configure="com.example.android.ExampleAppWidgetConfigure"//添加widget之前,先跳转到配置的activity进行相关参数配置,这个我们暂时用不到 10 android:resizeMode="horizontal|vertical"//widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以竖直拉伸 11 android:widgetCategory="home_screen|keyguard"//分别在屏幕主页和锁屏状态也能显示(4.2+系统才支持) 12 android:initialKeyguardLayout="@layout/example_keyguard"//锁屏状态显示的样式(4.2+系统才支持)> 13 </appwidget-provider>


3. 源码实现






【显示的布局】initialLayout布局;

【效果】


4. 反编译

4.1 反编译的工具







4.2 在项目中移植金山卫士的布局


【修改之后的布局】
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="wrap_content" 5 android:background="@drawable/widget_bg_portrait" 6 android:id="@+id/ll_root" 7 android:gravity="center_vertical" > 8 9 <LinearLayout 10 android:layout_width="0.0dip" 11 android:layout_height="fill_parent" 12 android:layout_marginLeft="5.0dip" 13 android:layout_weight="1.0" 14 android:background="@drawable/widget_bg_portrait_child" 15 android:gravity="center_vertical" 16 android:orientation="vertical" 17 android:paddingBottom="3.0dip" 18 android:paddingTop="3.0dip" > 19 20 <TextView 21 android:id="@+id/tv_process_count" 22 android:layout_width="wrap_content" 23 android:layout_height="wrap_content" 24 android:layout_marginLeft="10.0dip" /> 25 26 <ImageView 27 android:layout_width="fill_parent" 28 android:layout_height="wrap_content" 29 android:layout_marginBottom="1.0dip" 30 android:layout_marginTop="1.0dip" 31 android:background="@drawable/widget_bg_portrait_child_divider" /> 32 33 <TextView 34 android:id="@+id/tv_process_memory" 35 android:layout_width="wrap_content" 36 android:layout_height="wrap_content" 37 android:layout_marginLeft="10.0dip"/> 38 </LinearLayout> 39 40 <LinearLayout 41 android:layout_width="wrap_content" 42 android:layout_height="wrap_content" 43 android:gravity="center_horizontal" 44 android:orientation="vertical" > 45 46 <LinearLayout 47 android:layout_width="wrap_content" 48 android:layout_height="wrap_content" 49 android:gravity="center_vertical" > 50 51 <ImageView 52 android:layout_width="20.0dip" 53 android:layout_height="20.0dip" 54 android:src="@drawable/ic_launcher" /> 55 56 <TextView 57 android:layout_width="wrap_content" 58 android:layout_height="wrap_content" 59 android:text="@string/app_name" 60 android:textColor="#fff" /> 61 </LinearLayout> 62 63 <Button 64 android:id="@+id/btn_clear" 65 android:layout_width="90.0dip" 66 android:layout_height="wrap_content" 67 android:layout_centerVertical="true" 68 android:layout_marginTop="5.0dip" 69 android:background="@drawable/selector_next_btn_bg" 70 android:text="一键清理" 71 android:textColor="#fff" /> 72 </LinearLayout> 73 74 </LinearLayout>
【布局效果】


【效果】

5. 窗体小部件生命周期方法分析

【说明】在桌面上可以放置多个窗口小部件


1 package com.itheima.mobilesafe74.receiver; 2 3 import com.itheima.mobilesafe74.service.UpdateWidgetService; 4 5 import android.annotation.SuppressLint; 6 import android.appwidget.AppWidgetManager; 7 import android.appwidget.AppWidgetProvider; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.os.Bundle; 11 import android.util.Log; 12 13 @SuppressLint("NewApi") 14 public class MyAppWidgetProvider extends AppWidgetProvider { 15 private static final String tag = "MyAppWidgetProvider"; 16 @Override 17 public void onReceive(Context context, Intent intent) { 18 Log.i(tag, "onReceive............"); 19 super.onReceive(context, intent); 20 } 21 @Override 22 public void onEnabled(Context context) { 23 //创建第一个窗体小部件的方法 24 Log.i(tag, "onEnabled 创建第一个窗体小部件调用方法");27 super.onEnabled(context); 28 } 29 @Override 30 public void onUpdate(Context context, AppWidgetManager appWidgetManager, 31 int[] appWidgetIds) { 32 Log.i(tag, "onUpdate 创建多一个窗体小部件调用方法");35 super.onUpdate(context, appWidgetManager, appWidgetIds); 36 } 37 @Override 38 public void onAppWidgetOptionsChanged(Context context, 39 AppWidgetManager appWidgetManager, int appWidgetId, 40 Bundle newOptions) { 41 //当窗体小部件宽高发生改变的时候调用方法,创建小部件的时候,也调用此方法45 super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, 46 newOptions); 47 } 48 49 @Override 50 public void onDeleted(Context context, int[] appWidgetIds) { 51 Log.i(tag, "onDeleted 删除一个窗体小部件调用方法"); 52 super.onDeleted(context, appWidgetIds); 53 } 54 55 @Override 56 public void onDisabled(Context context) { 57 Log.i(tag, "onDisabled 删除最后一个窗体小部件调用方法");60 super.onDisabled(context); 61 } 62 }
【说明】将第一个小窗口放到桌面上,会调用onReceive(); onEnable();onUpdate();


【说明】在桌面上创建第2个窗口小部件


【说明】删除第一个窗口小部件


【说明】删除第二个窗口小部件;

【调用和停止服务的时机】


6. 开启服务
【说明】窗口小部件是在程序退出之后仍然在运行,因此需要使用服务;
【开启和关闭服务】


【创建服务】


【定时器任务】

【更新窗体部件中的内容】


【显示效果】

7.窗体小部件点击按钮杀死进程
【说明】
【1】在点击小部件的时候可以直接跳入到该应用;
【2】在点击一键清理按钮的时候可以清理后台的程序,并且显示框中的数据随着改变更新;

【说明】点击进入到程序中是在点击根部局除了一键清理按钮之外的地方都可以进入到应用中;
7.1 窗体小部件点击按钮功能

【延期的意图】不会立即执行intent意图,需要在满足某个条件的时候才触发该意图的发生,比如说:地雷的爆炸;

【此时的隐式意图】是应用程序的主界面;
【需要捕获的隐式意图的信息】

【隐式意图的开启】首先获取获取点击事件,执行隐式意图,进入到主界面;getActivity()的第四个参数PendingIntent.FLAG_CANCEL_CURRENT设置了程序在收到通知之后的显示形式;

【效果】在正常点击小部件的除了一键清理的之外的地方都可以进入到主程序界面,点击”一键清理“现在没有响应事件;

7.2 一键清理功能的完善
【原理说明】隐式意图:一键清理按钮会发送广播;在接收到广播之后执行内存清理的功能;



【新建广播接受者】执行杀死进程;

【效果】点击之后杀死后台进程并进行了显示的更新;

8. 锁屏&解锁定时任务开启&关闭
【说明】
【1】在关闭屏幕时,更新内存信息是没有必要的,停止更新内存信息,可以节省手机的功耗;
【2】在解锁屏幕的时候再开启定时的任务;
【框架】

【关闭定时更新任务】


【开启定时任务】

【注销广播】如果将程序移除,则没有必要再维护


【增加调试信息】

【测试效果】程序运行之后定时任务就开始执行;

【说明】在屏幕锁屏之后立刻停止了定时任务的运行;

【说明】在屏幕解锁之后立刻运行了定时任务;

浙公网安备 33010602011771号