本文来自 :http://blog.csdn.net/jjwwmlp456/article/details/38466969 (一)
http://blog.csdn.net/jjwwmlp456/article/details/38468259 (二)
源码地址:http://download.csdn.net/detail/u011549998/9273363 android studio项目 亲测
在屏幕上添加Widget:或长按屏幕空白处,或找到WidgetPreview App选择。原生系统4.0以下使用长按方式,4.0及以上 打开WIDGETS
创建Widget的一般步骤:
在menifest中
- <receiver android:name="com.stone.ui.TimerWidgetProvider">
- <intent-filter>
- <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
- <!-- 自定义action -->
- <action android:name="com.stone.action.start"/>
- </intent-filter>
- <meta-data android:name="android.appwidget.provider"
- android:resource="@xml/timer_widget_provider"/>
- <!-- android:resource="" 定义了Widget的信息使用timer_widget_provider.xml描述 -->
- </receiver>
Widget描述文件:timer_widget_provider.xml
- <?xml version="1.0" encoding="utf-8"?>
- <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
- android:minWidth="180dp"
- android:minHeight="40dp"
- android:updatePeriodMillis="5000"
- android:previewImage="@drawable/ic_launcher"
- android:initialLayout="@layout/timer_widget"
- android:resizeMode="horizontal|vertical"
- android:widgetCategory="keyguard|home_screen"
- android:configure="com.stone.ui.AppWidgetConfigureActivity" >
- <!--
- 计算size的公式: (70*n) -30 n为部件所需的大小(占几格) 当前的就是 3X1
- minResizeWidth
- minResizeHeight 能被调整的最小宽高,若大于minWidth minHeight 则忽略
- label 选择部件时看到标签
- icon 选择部件时看到图标
- updatePeriodMillis 更新时间间隔
- previewImage 选择部件时 展示的图像 3.0以上使用
- initialLayout 布局文件
- resizeMode 调整size模式
- configure 如果需要在启动前先启动一个Activity进行设置,在这里给出Activity的完整类名
- widgetCategory="keyguard|home_screen" widget可添加的位置 锁屏界面|桌面
- autoAdvanceViewId=@id/xx 与集合部件一起使用,指定该id所表示的集合的item自动推进
- 集合部件:3.0后才有。view:ListView、GridView、StackView、AdapterViewFilpper
- -->
- </appwidget-provider>
Widget使用的布局:timer_widget.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:background="@drawable/widget_background" >
- <TextView
- android:id="@+id/counter"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center"
- android:text="00:00"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearance"/>
- <ImageView
- android:id="@+id/start_stop"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:scaleType="center"
- android:src="@android:drawable/ic_media_play"/>
- </LinearLayout>
处理Widget相关事件的 AppWidgetProvider
- package com.stone.ui;
- import java.util.Arrays;
- import com.stone.R;
- import com.stone.service.TimerWidgetService;
- import android.app.PendingIntent;
- import android.appwidget.AppWidgetHost;
- import android.appwidget.AppWidgetManager;
- import android.appwidget.AppWidgetProvider;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.text.format.DateUtils;
- import android.widget.RemoteViews;
- /*
- * AppWidgetProvider 必须要接收android.appwidget.action.APPWIDGET_UPDATE 广播
- *
- */
- public class TimerWidgetProvider extends AppWidgetProvider {
- @Override //更新部件时调用,在第1次添加部件时也会调用
- public void onUpdate(Context context, AppWidgetManager appWidgetManager,
- int[] appWidgetIds) {
- super.onUpdate(context, appWidgetManager, appWidgetIds);
- System.out.println("onUpdate widget:" + Arrays.toString(appWidgetIds));
- /*
- * 构造pendingIntent发广播,onReceive()根据收到的广播,更新
- */
- Intent intent = new Intent(context, TimerWidgetService.class);
- PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
- RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.timer_widget);
- rv.setOnClickPendingIntent(R.id.start_stop, pendingIntent);
- appWidgetManager.updateAppWidget(appWidgetIds, rv);
- }
- @Override //部件从host中删除
- public void onDeleted(Context context, int[] appWidgetIds) {
- super.onDeleted(context, appWidgetIds);
- System.out.println("onDeleted widget");
- }
- @Override //第1次创建时调用,之后再创建不会调用
- public void onEnabled(Context context) {
- super.onEnabled(context);
- System.out.println("onEnabled widget");
- }
- @Override //当最后一个部件实例 被删除时 调用 用于清除onEnabled执行的操作
- public void onDisabled(Context context) {
- super.onDisabled(context);
- System.out.println("onDisabled widget");
- }
- @Override //
- public void onReceive(Context context, Intent intent) {
- super.onReceive(context, intent);
- System.out.println("onReceive widget");
- /*
- * 接收 <action android:name="com.stone.action.start"/>
- 在其他组件或activity或service中发送这些广播
- */
- if (intent.getAction().equals("com.stone.action.start")) {
- long time = intent.getLongExtra("time", 0);
- updateWidget(context, time);
- System.out.println("receive com.stone.action.start");
- }
- }
- private void updateWidget(Context context, long time) {
- //RemoteViews处理异进程中的View
- RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.timer_widget);
- System.out.println("time=" + time);
- rv.setTextViewText(R.id.counter, DateUtils.formatElapsedTime(time / 1000));
- AppWidgetManager am = AppWidgetManager.getInstance(context);
- int[] appWidgetIds = am.getAppWidgetIds(new ComponentName(context, TimerWidgetProvider.class));
- am.updateAppWidget(appWidgetIds, rv);//更新 所有实例
- }
- }
AppWidgetProvider中使用的TimerWidgetService
- package com.stone.service;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- public class TimerWidgetService extends Service {
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
- @Override
- public void onCreate() {
- super.onCreate();
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- /*
- * do some thing
- */
- //发送广播通知 widget 更新 状态
- sendBroadcast(new Intent("com.stone.action.start").putExtra("time", System.currentTimeMillis()));
- return Service.START_STICKY;
- }
- }