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());                 }             }         };

相關文章
相關標籤/搜索