360项目-10

# widget  #java

- 长按桌面, 或者在全部应用列表里向右滑动, 能够添加窗口小部件.
- 写一个类, 继承 AppWidgetProvider, 而后在清单文件里配置, 按照文档来就好了.
主要是 meta-data 标签里配置的 xml:android

        <!-- <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
            android:minWidth="40dp" 最小宽高
            android:minHeight="40dp"
            android:updatePeriodMillis="1800000" 多久更新一下Widget, 单位是毫秒, 最短是半个小时 1800000
            android:previewImage="@drawable/preview" 预览图片
            android:initialLayout="@layout/example_appwidget" 布局文件
            android:configure="com.example.android.ExampleAppWidgetConfigure" 配置页面
            android:resizeMode="horizontal|vertical" 缩放模式
            android:widgetCategory="home_screen"> 类型, 显示在桌面上, 仍是显示在锁屏界面上, API 17
        </appwidget-provider> -->app

-  修改布局, 反编译金山的apk, 反编译以后再清单文件里搜索, 把须要的文件所有拷贝过来
该拷的拷, 该删的删, 该改的改. 改完了别忘了修改清单文件
-  Widget的生命周期ide

        public class WidgetReceiver extends AppWidgetProvider{
            /**
             * 接收到事件
             */
            @Override
            public void onReceive(Context context, Intent intent) {
                super.onReceive(context, intent);
                System.out.println("onReceive");
            }
            /**
             * 第一次添加
             */
            @Override
            public void onEnabled(Context context) {
                super.onEnabled(context);
                System.out.println("onEnabled");
            }
            /**
             * 被添加(第一次, 或者再次添加)/更新
             */
            @Override
            public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
                super.onUpdate(context, appWidgetManager, appWidgetIds);
            }
            /**
             * 被删除
             */
            @Override
            public void onDeleted(Context context, int[] appWidgetIds) {
                super.onDeleted(context, appWidgetIds);
            }
            /**
             * 最后一个被删除
             */
            @Override
            public void onDisabled(Context context) {
                super.onDisabled(context);
            }
        }布局


-  定时更新Widget
看一下日志, 发现金山每隔一会就更新一下Widget, 它在配置文件里配的 android:updatePeriodMillis="0",
不依赖系统的更新, 它实际上是启动了一个服务, 在服务里作定时操做.
咱们也写一个服务, 定时更新Widget, 在 onEnabled 方法里启动, 在 onDisable 方法里中止
另外在 onUpdate 方法里也要起一下服务, 确保服务正在运行. 这是为了不桌面上已经有Widget,
而后直接在项目上右键 run as 不走 onEnabled 方法.
   
         /**
         * 被添加(第一次, 或者再次添加)/更新
         */
        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
            super.onUpdate(context, appWidgetManager, appWidgetIds);
            // onUpdate 方法里也要起一下服务, 确保服务正在运行. 避免桌面上已经有Widget,
            // 而后直接在项目上右键 run as 不走 onEnabled 方法.
            if (!ServiceStateUtil.isServiceRunning(context, UpdateWidgetService.class)) {
                context.startService(new Intent(context, UpdateWidgetService.class));
            }
        }
    
## 定时器 ##this

    java提供的Timer类
     private void timer1() {
        Timer timer = new Timer();
        参1 定时任务 参2 第一次执行的延时时间 参3 间隔
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("定时器: Timer");
            }
        }, 0, 3000);
        // 中止
        // timer.cancel();
    }日志

- 在相应的服务里: 在oncreate方法中  开启定时器
        component

           // 闹钟管理器 能够执行定时任务 而且应用退出也起做用 可是timer就不行
                am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
                Intent intent = new Intent();
                intent.setAction("com.itheima.mobilesafe.action.upwidget");
                // PendingIntent 延时的intent 对应的动做不会当即执行 须要有一个触发的事件
                // 这里是用定时器来触发发送一个广播
                operation = PendingIntent.getBroadcast(getApplicationContext(), 100, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
                // 参1 计时方式,参2 第一次执行的延时时间,参3执行间隔 参4 延时的intent
                am.setRepeating(AlarmManager.RTC, 2000, 5000, operation);orm

            //注册接受更新的广播
            IntentFilter filter = new IntentFilter();
            filter.addAction("com.itheima.mobilesafe.action.upwidget");
            registerReceiver(receiver, filter);xml


- 关于setRepeating的参数1计时方式  了解一下

        public   static   final   int  ELAPSED_REALTIME    
        // 当系统进入睡眠状态时,这种类型的闹铃不会唤醒系统。直到系统下次被唤醒才传递它,该闹铃所用的时间是相对时间,是从系统启动后开始计时的,包括睡眠时 间,能够经过调用SystemClock.elapsedRealtime()得到。系统值是3    (0x00000003)。     
            
        public   static   final   int  ELAPSED_REALTIME_WAKEUP    
        //能唤醒系统,用法同ELAPSED_REALTIME,系统值是2 (0x00000002) 。     
            
        public   static   final   int  RTC    
        //当系统进入睡眠状态时,这种类型的闹铃不会唤醒系统。直到系统下次被唤醒才传递它,该闹铃所用的时间是绝对时间,所用时间是UTC时间,能够经过调用 System.currentTimeMillis()得到。系统值是1 (0x00000001) 。     
            
        public   static   final   int  RTC_WAKEUP    
        //能唤醒系统,用法同RTC类型,系统值为 0 (0x00000000) 。     
            
        Public static   final   int  POWER_OFF_WAKEUP    
        //能唤醒系统,它是一种关机闹铃,就是说设备在关机状态下也能够唤醒系统,因此咱们把它称之为关机闹铃。受SDK版本影响,某些版本并不支持,使用方法同RTC类型,系统值为4(0x00000004)。


- 在注册的receiver里


            private BroadcastReceiver receiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    String action = intent.getAction();
                    if (TextUtils.equals(action, "com.itheima.mobilesafe.action.upwidget")) {
                        updateWidget();
                    }
                }
            };


            //更新Widget内容, 要使用 AppWidgetManager 这个类
            private void updateWidget() {
                // 获取 AppWidgetManager
                mWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
                // 初始化widget组件
                ComponentName provider = new ComponentName(this, WidgetReceiver.class);
                // 初始化远程view对象, 这个View不在咱们的应用进程里
                RemoteViews remoteView = new RemoteViews(getPackageName(), R.layout.process_widget);
                remoteView.setTextViewText(R.id.tv_running_num,
                        "正在运行的软件:" + ProcessInfoProvider.getRunningProcessCount(this));
                remoteView.setTextViewText(R.id.tv_avail_mem,
                        "可用内存:" + Formatter.formatFileSize(this, ProcessInfoProvider.getAvailMemory(this)));
                // 更新远程view
                mWidgetManager.updateAppWidget(provider, remoteView);
            }


- AppWidgetManager 和 ComponentName 初始化能够放在 onCreate 方法里.

- 在ondestroy里

        @Override
        public void onDestroy() {
            super.onDestroy();
            //服务结束取消定时器  和取消注册
            am.cancel(operation);
            unregisterReceiver(receiver);
        }


-  设置Widget的点击事件 仍是以前的 RemoteViews那里 增长点击事件就好


           Intent intent = new Intent();
        intent.setAction("com.itheima.mobilesafe.action.widgetclean");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 101,intent, PendingIntent.FLAG_UPDATE_CURRENT);
        //点击发送一个广播 去杀死进程
        views.setOnClickPendingIntent(R.id.btn_clear, pendingIntent);
        widgetManager.updateAppWidget(component, views);

> 以前 注册的广播增长一个action

        IntentFilter filter = new IntentFilter();
        filter.addAction("com.itheima.mobilesafe.action.upwidget");
        filter.addAction("com.itheima.mobilesafe.action.widgetclean");
        registerReceiver(receiver, filter);

> 广播接收者里也增长判断

        private BroadcastReceiver receiver = new BroadcastReceiver() {             @Override             public void onReceive(Context context, Intent intent) {                 String action = intent.getAction();                 if (TextUtils.equals(action, "com.itheima.mobilesafe.action.upwidget")) {                     updateWidget();                 } else if (TextUtils.equals(action, "com.itheima.mobilesafe.action.widgetclean")) {                     ProcessInfoProvider.killAllPro(getApplicationContext());                 }             }         };

相关文章
相关标签/搜索