AppWidget开发
来源:互联网 发布:docker mysql 连接 编辑:程序博客网 时间:2024/06/16 05:55
一.开发Widget步骤
官方文档
1.添加Widget的描述文档(xml)--对此Widget的相关设置,如宽和高,更新时间,显示Layout,Activity连接相关
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<!--一定要声明为appwidget-provider,则说明是widget应用程序-->
<appwidget-provider
android:minWidth="320dp"
android:minHeight="80"
android:updatePeriodMillis="10000"
<!--widget的显示布局界面-->
android:initialLayout="@/layout/activity_main">
</appwidget-provider>
2.创建一个继承自AppWidgetProvider的类,以实现对Widget的更新,其实AppWidgetProvider继承自BroadcastReceiver。
3.定义组件layout文件
4.配置Manifest
(1)添加Receiver,选择继承自AppwidgetProvider的类
(2)为继承自AppwidgetProvider类的类添加元数据meta-data
<meta-data
android:name="android.appwidget.provider"
<!--必须为android.appwidget.provider,描述此应用是个Widget程序-->
android:resource="@xml/widget_info"/>
<!--声明描述widget的xml文件位置-->
(3)添加Activity---如果有链接的话:
Intent-Filter:action--ACTION_APPWIDGET_CONFIGURE
在Info(xml)文件中声明configuration = “Activity所在包”
代码如下
<application
<receiver android:name="appWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_info"/>
</receiver> </application>
二.代码如下
res/xml/widget_info:Widget程序配置文件
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="100dp"
android:updatePeriodMillis="1000"
<!--更新时间-,ms级别->
android:initialLayout="@layout/activity_main"
Android:configure = “一个配置widget的界面,不是继承自AppWidget的那个类”>
<!--初始化布局界面,widget显示界面-->
</appwidget-provider>
相关属性
--android:minWidth/minHeight---声明widget的最小宽和高,参照下面的设计标准即可(4*1 3*3 。。。。。。)
--android:updatePeriodMillis
声明好久更新一次widget,通过调用onUpdate(),单位是ms。
不过,这个属性声明的时间实际上并不会太准,所以最好是使用一个alarm来实时更新widget,并且设置updatePeriodMillis=”0”即可。
--android:configure
配置widget的一个activity
--android:widgetCategory
声明appwidget是否能被放置到桌面和锁屏界面上--android:InitialKeyguardLayout
指定锁屏界面的layout和initialLayout原理是一样的。
res/layout/activity_widget
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/showText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="TextView" />
</RelativeLayout>
Src/com.ccp.wj.appwidget/AppWidget.java
public class appWidget extends AppWidgetProvider {
private static String []text = {"ccp", "wj", "chj"};
private static int count =0;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
if(count >= 2)count = 0;
count++;
update( context, appWidgetManager, appWidgetIds);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
private void update(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
RemoteViews rvs = new RemoteViews(context.getPackageName(),R.layout.activity_main);
rvs.setTextViewText(R.id.showText, text[count]);
appManager.updateWidget(appWidgetIds, rvs);//更新
}
}
Widget与布局通过RemoteViewsonic通信
Res/AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name="appWidget">
<intent-filter>
<!--public static final String ACTION_APPWIDGET_UPDATE
Added in API level 3
Sent when it is time to update your AppWidget.
This may be sent in response to a new instance for this AppWidget provider having been instantiated, the requested update interval having lapsed, or the system booting.
The intent will contain the following extras:
EXTRA_APPWIDGET_IDS
The appWidgetIds to update. This may be all of the AppWidgets created for this provider, or just a subset. The system tries to send updates for as few AppWidget instances as possible.
See Also
AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
Constant Value: "android.appwidget.action.APPWIDGET_UPDATE"
-->
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_info"/>
</receiver>
注:只有在第一次安装程序时才会加载widget
二.设计Widget
竖直方向vertical
Ceil piexl
4*1 320*100
4*2 320*200
3*3 240*300
2*2 160*200
水平方向horizon
4*1 424*74
3*3 318*222
2*2 212*148
三.指定一个Configure界面
即添加widget时,不是马上添加widget而是进入配置界面
1.在manifest中声明Activity
<activity android:name=".ExampleAppWidgetConfigure">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
2.在appwidget_info.xml中声明android:configure
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
...
android:configure="com.example.android.ExampleAppWidgetConfigure"
... >
</appwidget-provider>
四.为AppWidget的控件添加相应事件
调用setOnClickPendingIntent(int, PendintIntent)
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
// Create an Intent to launch ExampleActivity
Intent intent = new Intent(context, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
五.定时刷新widget
因为要考虑到省电等问题,所以在widget_info.xm文档中标识的android:updatePeriodMillis的时间并不能保证及时刷新,一般来说是30分钟,我们一般在onUpdate()中添加一个Service来保证widget的实时刷新,具体实现方法如在其他Activity中更新widget一样
更新widget
1.首先,从运行的Activity中获取widget的id
Intent intent = getIntent();Bundle extras = intent.getExtras();if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);}
2.配置appWidget的设置
3.配置完毕,通过getInstance(context)获取一个AppWidgetManager的实例。
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
4.通过updateAppWidget(int ,RemoteViews)由RemoteViews更新appWidget。
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
5.最后创建一个返回Intent,设置一个Activity Result并且finish掉这个Activity。
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
Tip:当你的configure Activity第一次打开,设置Activity的RESULT_CANCEL,这样,如果用户在配置之前就退出了,那么app widget host就会提醒这个配置取消了,并且不会被添加。
2.实现实时更新
--在onUpdate()中添加一个alarm,定时更发送广播并在广播接收器中更新widget
代码如下
appWidgetProvider
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
Log.d(tag, "onUpdate--widget刷新");
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
updateWidget(context,N,appWidgetManager,appWidgetIds);
//每分钟刷新一次时间
if(setCount<1)
setRefershWidgetTime(appWidgetIds);
}
/**
* 定时刷新widget的时间
* @param appWidgetIds
*/
public void setRefershWidgetTime(int[] appWidgetIds){
AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(StringHelper.WIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
int triggerTime = 60*1000;
am.setRepeating(AlarmManager.RTC, System.currentTimeMillis()+triggerTime, triggerTime, pi);
setCount++;
}
BroadcastReceiver
package com.ccp.wj.doit.receiver;
import com.ccp.wj.doit.utils.DateUtils;
import com.ccp.wj.doit.utils.StringHelper;
import com.ccp.wj.doit.widget.AppWidgetConfigureActivity;
import com.ccp.wj.doitweatherforcast.R;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.RemoteViews;
public class WidgetUpdateReceiver extends BroadcastReceiver {
private int h,m;
private int[]imgId=new int[4];
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle b = intent.getExtras();
if(b!=null){
int appWidgetIds[]= b.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
updateWidgetTime(context,appWidgetIds);
}
}
private void updateWidgetTime(Context context, int[] appWidgetIds) {
// TODO Auto-generated method stub
int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
widgetInit();
// Create an Intent to launch ExampleActivity
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout_4x1);
views.setImageViewResource(R.id.clock_0, imgId[0]);
views.setImageViewResource(R.id.clock_1, imgId[1]);
views.setImageViewResource(R.id.clock_2, R.drawable.widget_white);
views.setImageViewResource(R.id.clock_3, imgId[2]);
views.setImageViewResource(R.id.clock_4, imgId[3]);
//get the appWidgetManager
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
private void widgetInit() {
// TODO Auto-generated method stub
h = DateUtils.getHours();
m = DateUtils.getMinutes();
String hour[]=new String[2],minutues[]=new String[2],hh,mm;
if(h < 10){
imgId[0]=StringHelper.clock_img_id[0];
imgId[1]=StringHelper.clock_img_id[h];
}
else{
hh=String.valueOf(h);
hour[0]=hh.substring(0, 1);
hour[1]=hh.substring(1);
imgId[0] = StringHelper.clock_img_id[Integer.parseInt(hour[0])];
imgId[1]=StringHelper.clock_img_id[Integer.parseInt(hour[1])];
}
if(m<10){
imgId[2]=StringHelper.clock_img_id[0];
imgId[3]=StringHelper.clock_img_id[m];
}
else{
mm = String.valueOf(m);
minutues[0]=mm.substring(0, 1);
minutues[1]=mm.substring(1);
imgId[2] = StringHelper.clock_img_id[Integer.parseInt(minutues[0])];
imgId[3]=StringHelper.clock_img_id[Integer.parseInt(minutues[1])];
}
}
}
六.多个widget放置在桌面时响应事件混乱
当在屏幕上有多个widget时,无论在哪个widget上点击,响应事件的总是最后一个widget,原因就是PendingIntent传值时出现了错误,每次添加的新PendingIntent把原来的PendingIntent的替换掉了、
PendingIntent pi = PendintIntent.getBroadcast(context, 0, intent,0);
我们固定把第二个参数设置了为0.而第二个参数表示的是requestCode表示发送器的私有请求码,相当于pendingIntent的一个Id,PendingIntent会根据这个请求码来判断是否存在相同的PendingIntent,如果存在则替换,所以出现了以上情况。
建议PendingIntent pendingIntent = PendingIntent.getBroadcast(context,appWidgetId,intent,0);
七.获取widget的所有id--appWidgetIds
appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName("com.ccp.wj.doitweatherforcast","com.ccp.wj.doit.widget.DoItWeatherWidget"));
- AppWidget开发
- AppWidget开发
- appwidget实例 AppWidget开发实例 [复制链接]
- android appwidget开发
- appwidget开发笔记
- android appwidget 开发
- Android AppWidget开发心得
- 【Android AppWidget开发流程】
- appWidget开发实例
- Android:AppWidget开发流程
- Android AppWidget开发实战
- AppWidget开发实例
- Android AppWidget开发
- AppWidget的开发
- Android AppWidget数字时钟开发
- Android之AppWidget 开发浅析
- Android之AppWidget 开发浅析
- Appwidget
- [ax]WebBrowser.ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt) 参数列表及说明
- Hibernate Examples
- HDU 2159 二维完全背包
- Java 重定向和请求转发的区别
- AppCan UI2.0架构中CSS类弹性盒子样式封装
- AppWidget开发
- NYOJ 336 子序列
- 关于安装BlueStacks(蓝手指Android模拟器)失败的问题
- Ubuntu 网卡配置文件/etc/network/interfaces重启失效
- 深入理解成员函数的重载、隐藏、覆盖
- static
- [LeetCode] Binary Tree Preorder Traversal
- 小强的HTML5移动开发之路(44)——JqueryMobile中的按钮
- iOS应用直接调跳转到评价页面和应用下载页面