widget的进一步使用,利用AppWidgetProvider实现桌面的时钟挂件

1、通过上面介绍widget的基本应用外面知道,系统最多30分钟才更新挂件的内容,为了实时更新时钟我们必须自己发送广播来实现挂件内容的更新,其方法就是覆写父类AppWidgetProvider的onReceive()方法,并在注册的广播接收的intent-fliter里添加接受自己的广播。

2、用过查看Mainfest文件知道广播接受原始只注册了android.appwidget.action.APPWIDGET_UPDATE,但是可以接收android.appwidget.action.APPWIDGET_ENABLED,android.appwidget.action.APPWIDGET_DISENABLED,猜想AppWidgetProvider里的接受者在系统里已经注册了接收这些广播,而我写的类继承它,因此也可以接收。

3、当我去掉注册的android.appwidget.action.APPWIDGET_UPDATE只保留我自己添加的更新时间的广播时候却收不到android.appwidget.action.APPWIDGET_UPDATE等一些广播了并且在widget里找不到我定义的挂件了。猜想在系统定义了相应的规则,必须注册了的广播中含有android.appwidget.action.APPWIDGET_UPDATE,且注册的类必须继承了AppWidgetProvider才会在系统里注册一个挂件,并且继承的类可以收到AppWidgetProvider接受的广播。

4、 当我们在存储widgetId时候数据不加static时候发现每次接收到信号时候widgetIds这个集合的size都为0,表明每次接受到广播后就重新创建了NewAppWidge这个类对象。因此在广播类中重要的数据得用static变量。

5 广播机制:广播在mainfest里注册后,当接受到相应的广播后就会创建相应注册在receiver的类,然后由这些类的onreceiver来处理,处理后当系统内存不足的时候就会回收这个对象,然后下次收到的时候就会再次重新创建对象。

下面给出实现的demo:

widget类:

package com.example.user.appwidget;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.RemoteViews;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;

/**
 * Implementation of App Widget functionality.
 */
public class NewAppWidget extends AppWidgetProvider {

    private final  static  String Action_UpDateTime ="android.appwidget.action.APPWIDGET_UPDATE";
    private final  static  String Action_Enable ="android.appwidget.action.APPWIDGET_ENABLED";
    private  static  ArrayList<Integer> widgetIds = new ArrayList<>();

    private static boolean  HasUpdateThread = false;
    Thread upWidget= null;

    @Override
    public void onReceive(Context context, Intent intent) {

        int size = widgetIds.size();
        int [] widgetIdArray =  new int [size];
        for(int i = 0 ; i < size ; i++)
        {
            widgetIdArray[i] = widgetIds.get(i);
        }

        onUpdate(context , AppWidgetManager.getInstance(context) , widgetIdArray );

        System.out.println("收到了广播" + intent.getAction());

        super.onReceive(context, intent);
    }

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) {
        Calendar c = Calendar.getInstance();
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int seconds = c.get(Calendar.SECOND);
        CharSequence widgetText = "Time:" + hour + ":" + minute + ":" + seconds;//context.getString(R.string.appwidget_text);
        // Construct the RemoteViews object
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
        views.setTextViewText(R.id.appwidget_text, widgetText);

        // Instruct the widget manager to update the widget
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }


    // 到达指定更新时间(new_app_widget_info.xml中指定的,大于30分钟才有效,小于30分钟会30分钟执行一次)
    // 或者向桌面添加Widget时候执行
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // There may be multiple widgets active, so update all of them
        for (int appWidgetId : appWidgetIds)
        {
            updateAppWidget(context, appWidgetManager, appWidgetId);
            if(!widgetIds.contains((Integer)appWidgetId))
            {
                System.out.println("不含有挂件"+appWidgetId);
                widgetIds.add((Integer) appWidgetId);
            }
            else
                System.out.println("含有挂件"+appWidgetId);
        }
        if (!HasUpdateThread)
        {
            System.out.println("创建了一个进程");HasUpdateThread =true;
            upWidget = new UpDateWiget(context);
            upWidget.start();

        }
    }

    //当第一个widget创建时候执行
    @Override
    public void onEnabled(Context context) {
        // Enter relevant functionality for when the first widget is created
//        System.out.println("1111111111111111111111111111111111111111111111");

    }

    //当最后一个widget实例被删除时执行
    @Override
    public void onDisabled(Context context) {
        // Enter relevant functionality for when the last widget is disabled
    }

    class UpDateWiget extends Thread {
//        public int widgetId;
        public Context context;

        public UpDateWiget(Context context) {
//            this.widgetId = widgetId;
            this.context = context;
        }

        @Override
        public void run() {
            while (true) {
                Intent intent = new Intent("android.appwidget.action.APPWIDGET_UPDATETIME");
//                intent.putExtra("wigetId", widgetId);
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("发送了一条广播");
                context.sendBroadcast(intent);
            }
        }
    }

}

  挂件的布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#09C"
    android:padding="@dimen/widget_margin">

    <TextView
        android:id="@+id/appwidget_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_margin="8dp"
        android:background="#09C"
        android:contentDescription="@string/appwidget_text"
        android:text="ca"
        android:textColor="#ffffff"
        android:textSize="20dp"
        android:textStyle="bold|italic" />

</RelativeLayout>

  mainfset里注册的广播:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.user.appwidget">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".NewAppWidget">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="android.appwidget.action.APPWIDGET_UPDATETIME"/>
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/new_app_widget_info" />
        </receiver>

    </application>

</manifest>

  

 

posted @ 2016-10-17 10:08  Lammy  阅读(2151)  评论(0编辑  收藏  举报