android中Appwidget的使⽤
我们常见的桌⾯⼩插件,例如⼀个桌⾯上系统setgings开关组合,可以控制蓝⽛,wifi是否开启,例如⼀个桌⾯的⼩天⽓等等;这些都是Appwidget的使⽤例⼦。
下⾯介绍如何使⽤Appwidget;
在使⽤的过程中涉及到⼀些关键类,下⾯⼀⼀列举:
1.AppWidget provider:
该类是BroadcastReceiver的⼦类,⾥⾯的onReceive⽅法⾥实现了对⼏个常⽤的action的监听;
例如:
AppWidgetManager.ACTION_APPWIDGET_UPDATE
AppWidgetManager.ACTION_APPWIDGET_DELETED
AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED
AppWidgetManager.ACTION_APPWIDGET_ENABLED
AppWidgetManager.ACTION_APPWIDGET_DISABLED
AppWidgetManager.ACTION_APPWIDGET_RESTORED
当接收到其中⼀个时,会调⽤对应的空的实现⽅法,你可以在你继承该AppWidgetProvider的类中
有选择的重写如下⽅法:
onReceive(Context, Intent):
除了上⾯的⼏种action监听外,你还可以⾃⼰定义⼀些来监听。
void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds):
当需要提供RemoteViews时调⽤
void onDeleted(Context context, int[] appWidgetIds)
当widget实例被删除时调⽤
void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, Bundle newOptions)
当widget的⼤⼩发⽣改变时调⽤,
void onEnabled(Context context)
当第⼀个widget被实例化时调⽤,
void onDisabled(Context context)
最后⼀个widget实例被删除时调⽤,
void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds)安卓intent用法
当widget实例备份恢复时调⽤,
2.AppWidgetManager:
⽤来更新widiget的状态和获取已经安装的widget的信息,AppWidgetManager getInstance(Context context)获取实例。
该类中也有⼀些⽅法可以看看
updateAppWidget(int[] appWidgetIds, RemoteViews views)可以在ACTION_APPWIDGET_UPDATE执⾏
其中views⾥⾯的view持有的bitmap所占内存不能超过screen width x screen height x 4 x 1.5字节
notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)
更新数据
List<AppWidgetProviderInfo> getInstalledProviders()
获取已经安装的AppWidget
AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId)
根据id获取Info
3. AppWidgetProviderInfo:
⽤来描述widget的属性,在res/xml/定义如:
<span ><appwidget-provider xmlns:android="schemas.android/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:updatePeriodMillis="86400000"
android:previewImage="@drawable/preview"
android:initialLayout="@layout/example_appwidget"
android:configure="ample.android.ExampleAppWidgetConfigure"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen|keyguard"
android:initialKeyguardLayout="@layout/example_keyguard">
</appwidget-provider></span>
⼀些常⽤属性介绍:
<span >resizeMode :RESIZE_NONE,RESIZE_HORIZONTAL,RESIZE_VERTICAL,RESIZE_BOTH:在某些⽅向上的⼤⼩是否可调widgetCategory:WIDGET_CATEGORY_HOME_SCREEN,WIDGET_CATEGORY_KEYGUARD:在桌⾯或者锁屏界⾯显⽰
ComponentName:对应的是widget在manifest中的name属性
minWidth,minHeight:最⼩宽和⾼,单位dp
minResizeWidth 和 minResizeHeight :
使⽤这两个属性,可以允许⽤户重新调整 widget 的⼤⼩,使 widget 的⼤⼩可以⼩于 minWidth 和 minHeight。
updatePeriodMillis,更新频率,单位ms,最好设置为不要⽐1⼩时更短的时间,如果短于30分钟,系统还是只会30分钟⼀次。这个使系统实现的更新机制。
如果我们要更短的话,就只有使⽤service,AlarmManager
initialLayout,widget添加到桌⾯时的初始布局
initialKeyguardLayout,widget在添加到锁屏界⾯的初始布局,只有当category是在锁屏类型时有效。
configure:定义了 widget 的配置 Activity
previewImage:指定预览图,该预览图在⽤户选择 widget 时出现,如果没有提供,则会显⽰应⽤的图标</span>
⼀些关键说明:
默认情况下(即不设置android:widgetCategory属性),Android是将widget添加到 home screen 中。但在Android 4.2中,若⽤户希望 widget 可以被添加到lock screen中,可以通过设置 widget 的 android:widgetCategory 属性包含keyguard来完成。
当你把 widget 添加到lock screen中时,你可能对它进⾏定制化操作,以区别于添加到home screen中的情况。 你能够通过 getAppWidgetOptions() 来进⾏判断 widget 是被添加到lock screen中,还是home screen中。通过 getApplicationOptions() 获取 Bundle对象,然后读取 Bundle 的
OPTION_APPWIDGET_HOST_CATEGORY值:若值为 WIDGET_CATEGORY_HOME_SCREEN,
则表⽰该 widget 被添加到home screen中; 若值为WIDGET_CATEGORY_KEYGUARD,则表⽰该 widget 被添加到lock screen中。
布局中的问题:
布局时要留有widget的margin,padding
⼤⼩设置:70 × n − 30,n为多少⾏或列
⽀持的根布局:
FrameLayout
LinearLayout
RelativeLayout
GridLayout
⽀持的控件:
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper
使⽤例⼦:
⾸先要定义⼀个AppWidgetProvider ,这⾥继承该类;ExampleAppWidgetProvider.java
<span >ample.sample;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
t.Context;
t.Intent;
import android.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
@SuppressLint("NewApi")
public class ExampleAppWidgetProvider extends AppWidgetProvider {
// 保存 widget 的id的HashSet,每新建⼀个 widget 都会为该 widget 分配⼀个 id。 private static Set idsSet = new HashSet();
// 按钮信息
private static final int BUTTON_SHOW = 1;
// 图⽚数组
private static final int[] ARR_IMAGES = { R.drawable.sample_0,
R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3,
R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6,
R.drawable.sample_7, };
private static final String TAG = "Provider";
private static Intent intent;
// 第⼀个widget被创建时调⽤
@Override
public void onEnabled(Context context) {
Log.d(TAG, "onEnabled");
/
/ 在第⼀个 widget 被创建时,开启服务
// 在第⼀个 widget 被创建时,开启服务
intent = new Intent(context, ExampleAppWidgetService.class);
context.startService(intent);
}
// 最后⼀个widget被删除时调⽤
@Override
public void onDisabled(Context context) {
Log.d(TAG, "onDisabled");
// 在最后⼀个 widget 被删除时,终⽌服务
context.stopService(intent);
}
@Override
public void onReceive(Context context, Intent intent) {
final String action = Action();
Log.d(TAG, "OnReceive:Action: " + action);
if (ExampleAppWidgetService.UPDATE_WIDGET_ACTION.equals(action)) {
// “更新”⼴播
updateAllAppWidgets(context, Instance(context),
idsSet);
} else if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {
/
/ “按钮点击”⼴播
Uri data = Data();
int buttonId = Integer.SchemeSpecificPart());
if (buttonId == BUTTON_SHOW) {
Log.d(TAG, "Button wifi clicked");
Toast.makeText(context, "Button Clicked", Toast.LENGTH_SHORT)
.show();
}
}
}
// onUpdate() 在更新 widget 时,被执⾏,
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,  int[] appWidgetIds) {
Log.d(TAG, "onUpdate(): appWidgetIds.length=" + appWidgetIds.length);
// 每次 widget 被创建时,对应的将widget的id添加到set中
for (int appWidgetId : appWidgetIds) {
idsSet.add(Integer.valueOf(appWidgetId));
}
prtSet();
}
// 当 widget 被初次添加或者当 widget 的⼤⼩被改变时,被调⽤
@Override
public void onAppWidgetOptionsChanged(Context context,
AppWidgetManager appWidgetManager, int appWidgetId,
Bundle newOptions) {
}
// widget被删除时调⽤
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
Log.d(TAG, "onDeleted(): appWidgetIds.length=" + appWidgetIds.length);
// 当 widget 被删除时,对应的删除set中保存的widget的id
for (int appWidgetId : appWidgetIds) {
}
prtSet();
prtSet();
}
// 更新所有的 widget
private void updateAllAppWidgets(Context context,
AppWidgetManager appWidgetManager, Set set) {
Log.d(TAG, "updateAllAppWidgets(): size=" + set.size());
// widget 的id
int appID;
/
/ 迭代器,⽤于遍历所有保存的widget的id
Iterator it = set.iterator();
while (it.hasNext()) {
appID = ((Integer) it.next()).intValue();
// 随机获取⼀张图⽚
int index = (new java.util.Random().nextInt(ARR_IMAGES.length));
Log.d(TAG, "onUpdate(): index=" + index);
// 获取 l 对应的RemoteViews
RemoteViews remoteView = new PackageName(),    ample_appwidget);
// 设置显⽰图⽚
remoteView.setImageViewResource(R.id.iv_show, ARR_IMAGES[index]);
// 设置点击按钮对应的PendingIntent:即点击按钮时,发送⼴播。
remoteView.setOnClickPendingIntent(R.id.btn_show,
getPendingIntent(context, BUTTON_SHOW));
// 更新 widget
appWidgetManager.updateAppWidget(appID, remoteView);
}
}
private PendingIntent getPendingIntent(Context context, int buttonId) {
Intent intent = new Intent();
intent.setClass(context, ExampleAppWidgetProvider.class);
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
intent.setData(Uri.parse("custom:" + buttonId));
PendingIntent pi = Broadcast(context, 0, intent, 0);
return pi;
}
// 调试⽤:遍历set
private void prtSet() {
int index = 0;
int size = idsSet.size();
Iterator it = idsSet.iterator();
Log.d(TAG, "total:" + size);
while (it.hasNext()) {
Log.d(TAG, index + " -- " + ((Integer) it.next()).intValue());
}
}
}
</span>
接着在res下建⽴xml⽂件夹,在⽂件夹下定义⼀个⽂件来描述该provider example_l

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。