AppWidgetProvider的使用

来源:互联网 发布:定居中国的外国人知乎 编辑:程序博客网 时间:2024/05/06 14:25

一介绍:

AppWidgetProvider 是Android用于生成桌面小部件的类,它继承自BroadCastReceiver.所以它本质

上是一个广播接受者,谨记这一点,AppWidgerProvider的很多功能都好理解了。如图:



二开发一个桌面小部件的步骤

我会根据一个小demo,来记录整个桌面的开发流程,先看一下demo的效果(是一个时钟和文本

用来形象的显示时间,日期)。



实现具体步骤:

1,定义小部件的界面布局

定义res/layout/appwidget_clock.xml(文件名可以自定义),根据你的需求编写布局(即你希望你的小部件的样子)。

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <ImageView        android:id="@+id/id_iv_clock"        android:layout_width="150dp"        android:layout_height="150dp"        android:layout_centerInParent="true"        android:background="@android:color/transparent"/>    <TextView        android:id="@+id/id_tv_clock"        android:layout_width="150dp"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:layout_below="@+id/id_iv_clock"        android:textColor="@android:color/white"        android:background="@android:color/transparent"        android:gravity="center"        android:text="02/16 周四 上午 10:30"/></RelativeLayout>

2,配置小部件的配置信息

定义res/xml/appwidget_clock(文件名可自定义),添加如下内容

<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"    android:minHeight="150dp"    android:minWidth="150dp"    android:initialLayout="@layout/appwidget_clock"    android:updatePeriodMillis="0"></appwidget-provider>

其中minWidth与minHeight定义小部件的宽高,initialLayout初始化布局文件。updatePeriodMillis更新的周期(0表示没有更新周期)。


3,定义小部件类,继承AppWidgetProvider。

/** *  * 最重要的方法有两种onReceive, onUpdate. * onUpdate, 小部件被加载到桌面 * onReceive,自定义的点击事件(即发送自定义的广播,在这里接收并处理)。 */public class AppWidgetClockProvider extends AppWidgetProvider {    public static final String tag = "AppWidgetClockProvider";    private static RemoteViews remoteViews;    //自定义的广播Action。    public static final String AppWidget_Click_Action = "com.example.littledemo.appwidgetclockprovider";    //自定义的时钟的Drawable,根据当前的时间,绘制正确的图形。    ClockDrawable clockDrawable;    //用于实现,每隔一秒更新桌面小部件,(最好应该启动service定时跟新小部件,因为广播接收器的生命周期很短)    Timer timer;    Handler handler = new Handler(){        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);        }    };        /**     * 接收广播     * @param context     * @param intent     */    @Override    public void onReceive(Context context, Intent intent) {        super.onReceive(context, intent);        LogUtil.i(tag, "onReceive");        String action = intent.getAction();        LogUtil.i(tag, "action" + action);        //接收到click点击事件发送的广播,启动主界面(响应点击事件)        if(AppWidget_Click_Action.equals(action)){            Intent in = new Intent(context, AppWidgetActivity.class);            in.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);            context.startActivity(in);        }    }    /**     * 小部件被更新时,调用方法     * (原以为响应updatePeriodMillis 定义的周期,但其实没有。)     * @param context     * @param appWidgetManager     * @param appWidgetIds     */    @Override    public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) {        super.onUpdate(context, appWidgetManager, appWidgetIds);        LogUtil.i(tag, "onUpdate");        //启动定义任务,更新小部件        if(timer == null){            timer = new Timer();            timer.schedule(new TimerTask() {                @Override                public void run() {                    handler.post(new Runnable() {                        @Override                        public void run() {                            for (int i = 0; i < appWidgetIds.length; i++) {                                onWidgetUpdate(context, appWidgetManager, appWidgetIds[i]);                            }                        }                    });                }            }, 0, 1000);        }    }    private void onWidgetUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetId){        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget_clock);        //设置点击事件        Intent intent = new Intent(AppWidget_Click_Action);        PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, 0);        remoteViews.setOnClickPendingIntent(R.id.id_iv_clock, pIntent);        //更新小部件,图标        if(clockDrawable == null){            clockDrawable = new ClockDrawable(context);            clockDrawable.setBounds(0, 0, PixelUtil.dp2px(150, context),PixelUtil.dp2px(150, context));        }        Bitmap bitmap = BitmapUtil.drawable2Bitmap(clockDrawable);        remoteViews.setImageViewBitmap(R.id.id_iv_clock, bitmap);        //更新部件文本        String txt = StringUtil.getAppWidgetTxt();        remoteViews.setTextViewText(R.id.id_tv_clock, txt);        //更新部件        appWidgetManager.updateAppWidget(appWidgetId, remoteViews);        bitmap.recycle();    }    /**     * 每删除一次窗口小部件,就调用一次     *     * @param context     * @param appWidgetIds     */    @Override    public void onDeleted(Context context, int[] appWidgetIds) {        super.onDeleted(context, appWidgetIds);        LogUtil.i(tag, "onDeleted");        LogUtil.i(tag, "timer is" + timer != null? "timer" : null);        if(timer != null){            timer.cancel();        }        timer = null;    }    /**     * 当最后一个窗口小部件被删除时,调用此方法     *     * @param context     */    @Override    public void onDisabled(Context context) {        super.onDisabled(context);        LogUtil.i(tag, "onDisabled");    }    /**     * 当第一个框口小部件第一次被添加到桌面,调用此方法     *     * @param context     */    @Override    public void onEnabled(Context context) {        super.onEnabled(context);        LogUtil.i(tag, "onEnabled");    }    @Override    public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {        super.onRestored(context, oldWidgetIds, newWidgetIds);        LogUtil.i(tag, "onRestored");    }    @Override    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {        super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);        LogUtil.i(tag, "onAppWidgetOptionsChanged");    }}

4,在AndroidMinifest.xml中声明小部件类

        <receiver android:name=".appwidget.AppWidgetClockProvider">            <meta-data                android:name="android.appwidget.provider"                android:resource="@xml/appwidget_clock">            </meta-data>            <intent-filter>                <action android:name="com.example.littledemo.appwidgetclockprovider"></action>                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>                <action android:name="android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"></action>                <action android:name="android.appwidget.action.APPWIDGET_RESTORED"></action>                <action android:name="android.appwidget.action.APPWIDGET_DELETED"></action>            </intent-filter>        </receiver>

注意,<actionandroid:name="android.appwidget.action.APPWIDGET_UPDATE"></action>是必须添加的

如果不添加,则不发出现在小部件的列表中。其中

<action android:name="com.example.littledemo.appwidgetclockprovider"></action>
是自定义的Action,是小部件上的点击事件所要发送的广播Action;
下面附上一个工具的类的代码:
自定义ClockDrawable:
public class ClockDrawable extends Drawable {    private Paint mPaint;    private final static int C_default = Color.WHITE;    private final static String tag = "ClockDrawable";    private Context mContext;    private int padding = 2;    public ClockDrawable(Context context) {        this.mContext = context;        mPaint = new Paint();        mPaint.setAntiAlias(true);        mPaint.setColor(C_default);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeWidth(PixelUtil.dp2px(2, mContext));        mPaint.setTextSize(PixelUtil.sp2px(12, mContext));        padding = PixelUtil.dp2px(padding, mContext);    }    @Override    public void draw(Canvas canvas) {        LogUtil.i(tag, "draw");        final Rect rect = getBounds();        //画圆        drawCircle(rect, canvas);        //画竖线        drawVerLine(rect, canvas);        //画数字        drawNum(rect, canvas);        //画时针和分针        drawHourMinuteHand(rect, canvas);    }    private void drawCircle(Rect rect, Canvas canvas) {        float cx = rect.exactCenterX();        float cy = rect.exactCenterY();        float radius = Math.min(cx, cy) - padding;        canvas.drawCircle(cx, cy, radius, mPaint);        canvas.drawCircle(cx, cy, PixelUtil.dp2px(2, mContext), mPaint);    }    private void drawVerLine(Rect rect, Canvas canvas) {        float cx = rect.exactCenterX();        float cy = rect.exactCenterY();        for (int i = 0; i < 12; i++) {            canvas.save();            canvas.rotate(30 * i, cx, cy);            canvas.drawLine(cx, padding, cx, padding + PixelUtil.dp2px(5, mContext), mPaint);            canvas.restore();        }    }    private void drawNum(Rect rect, Canvas canvas) {        float cx = rect.exactCenterX();        float cy = rect.exactCenterY();        for (int i = 0; i < 12; i++) {            canvas.save();            String txt = "" + i;            if (i == 0) {                txt = "12";            }            Rect tempRect = new Rect();            mPaint.getTextBounds(txt, 0, txt.length(), tempRect);            if (i == 0 || i == 1 || i == 2 || i == 10 || i == 11) {                canvas.rotate(30 * i, cx, cy);                float x = cx - tempRect.width() / 2.0f;                float y = padding + PixelUtil.dp2px(5, mContext) + tempRect.height();                canvas.drawText(txt, x, y, mPaint);            } else if (i == 3) {                float x = rect.width() - padding - tempRect.width() - PixelUtil.dp2px(5, mContext);                float y = rect.height() / 2.0f + tempRect.height() / 2.0f;                canvas.drawText(txt, x, y, mPaint);            } else if (i == 9) {                float x = padding + PixelUtil.dp2px(5, mContext);                float y = rect.height() / 2.0f + tempRect.height() / 2.0f;                canvas.drawText(txt, x, y, mPaint);            } else {                canvas.rotate(30 * (i - 6), cx, cy);                float x = cx - tempRect.width() / 2.0f;                float y = rect.height() - padding - PixelUtil.dp2px(5, mContext);                canvas.drawText(txt, x, y, mPaint);            }            canvas.restore();        }    }    private void drawHourMinuteHand(Rect rect, Canvas canvas) {        float cx = rect.exactCenterX();        float cy = rect.exactCenterY();        Calendar calendar = Calendar.getInstance();        int hour = calendar.get(Calendar.HOUR_OF_DAY);        int minutes = calendar.get(Calendar.MINUTE);        int second = calendar.get(Calendar.SECOND);        int rotate = (int) (360f * (hour * 60 * 60 + minutes * 60 + second) / (12 * 60.0f * 60));        LogUtil.i(tag, "hour:" + hour + " minutes:" + minutes + " second:" + second + " rotate:" + rotate);        canvas.save();        canvas.rotate(rotate, cx, cy);        canvas.drawLine(cx, cy - rect.height() / 6.0f, cx, cy + rect.height() / 10.0f, mPaint);        canvas.restore();        canvas.save();        canvas.rotate(360 * (minutes * 60 + second) / (60 * 60.0f), cx, cy);        canvas.drawLine(cx, cy - rect.height() / 4.0f, cx, cy + rect.height() / 10.0f, mPaint);        canvas.restore();    }    @Override    public void setBounds(Rect bounds) {        super.setBounds(bounds);    }    @Override    public void setAlpha(int alpha) {        mPaint.setAlpha(alpha);    }    @Override    public void setColorFilter(ColorFilter colorFilter) {        mPaint.setColorFilter(colorFilter);    }    @Override    public int getOpacity() {        return PixelFormat.TRANSLUCENT;    }}

BItmapUtil
public class BitmapUtil {    /**     * 根据Drawaable转Bitmap     * @param drawable     * @return     */    public static Bitmap drawable2Bitmap(Drawable drawable){        Bitmap bitmap = Bitmap.createBitmap(drawable.getBounds().width(), drawable.getBounds().height(), Bitmap.Config.ARGB_8888);        Canvas canvas = new Canvas(bitmap);        drawable.draw(canvas);        return bitmap;    }}

StringUtil
public class StringUtil {    private static String[] weeks = new String[]{            "周日", "周一","周二"," 周三","周四","周五","周六"    };    public static String getAppWidgetTxt(){        Calendar calendar = Calendar.getInstance();        int month = calendar.get(Calendar.MONTH) + 1;        int day = calendar.get(Calendar.DAY_OF_MONTH);        int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);        int am = calendar.get(Calendar.AM_PM);        StringBuffer sb = new StringBuffer();        sb.append(month+ "/" + day + " ")                .append(weeks[day_of_week - 1] + " ")                .append(am == 0 ? "上午 " : "下午 ")                .append(SDFUtil.format("hh:mm", calendar.getTimeInMillis()));        return sb.toString();    }}









0 0
原创粉丝点击