Android AppWidget开发心得

这几天公司要求开发一个手机应用的widget,刚开始只是懂得不多这方面的知识,但是通过这几天的研究现在把这几天的研究成果做个终结,顺便分享给大家。

每个Widget其实就是一个BroadcastReceiver,它们用XML metadata来描述Widget的细节。AppWidget framework通过Broadcast  intents和Widget通信,Widget的更新使用RemoteView来发送的。RemoteViews被包装成一个layout和特定内容来显示到桌面上。下面我来简单的介绍下Widget的开发:

1.定义一个类命名为ExampleAppWidgetProvider 继承类AppWidgetProvider,通过这个类来处理Widget中的一些事件响应等的一些操作,代码如下

/**
 * 为手机添加桌面控件,当点击桌面控件时则进入主程序
 * 
 * AppWidgetProvider:继承自BroadcastRecevier,在AppWidget应用update、enable、
 * disable和delete时接收通知。 其中,onUpdate、onReceive是最常用到的方法,它们接收更新通知
 */
public class ExampleAppWidgetProvider extends AppWidgetProvider {

	/**
	 * 用来间隔的更新App
	 * Widget,间隔时间用AppWidgetProviderInfo里的updatePeriodMillis属性定义(单位为毫秒)。
	 * 注意:SDK1.5之后此android:updatePeriodMillis就失效了,要自己创建service更新。 这个方法也会在用户添加App
	 * Widget时被调用,因此它应该执行基础的设置,比如为视图定义事件处理器并启动一个临时的服务Service,如果需要的话。
	 * 但是,如果你已经声明了一个配置活动,这个方法在用户添加App Widget时将不会被调用,
	 * 而只在后续更新时被调用。配置活动应该在配置完成时负责执行第一次更新。
	 */
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
		System.out.println("onUpdate");
		// 点击桌面组件时进入主程序入口
		Intent intent = new Intent(context, ABMainActivity.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
		// RemoteViews类描述了一个View对象能够显示在其他进程中,可以融合layout资源文件实现布局。
		// 虽然该类在android.widget.RemoteViews而不是appWidget下面,但在Android
		// Widgets开发中会经常用到它,
		// 主要是可以跨进程调用(appWidget由一个服务宿主来统一运行的)。
		RemoteViews myRemoteViews = new RemoteViews(context.getPackageName(), R.layout.my_layout);
		// myRemoteViews.setImageViewResource(R.id.imageView,
		// R.drawable.png1);//设置布局控件的属性(要特别注意)
		myRemoteViews.setOnClickPendingIntent(R.id.btn, pendingIntent);
		//Button button = (Button)View.findViewByID(R.id.btn);
		ComponentName myComponentName = new ComponentName(context, ExampleAppWidgetProvider.class);
		// 负责管理AppWidget,向AppwidgetProvider发送通知。提供了更新AppWidget状态,获取已经安装的Appwidget提供信息和其他的相关状态
		AppWidgetManager myAppWidgetManager = AppWidgetManager.getInstance(context);
		myAppWidgetManager.updateAppWidget(myComponentName, myRemoteViews);
	}

	/**
	 * 当App Widget从宿主中删除时被调用。
	 */
	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		System.out.println("onDeleted");
		super.onDeleted(context, appWidgetIds);
	}

	/**
	 * 当一个App Widget实例第一次创建时被调用。 比如,如果用户添加两个App Widget实例,只在第一次被调用。
	 * 如果你需要打开一个新的数据库或者执行其他对于所有的App Widget实例只需要发生一次的设置, 那么这里是完成这个工作的好地方。
	 */
	@Override
	public void onEnabled(Context context) {
		System.out.println("onEnabled");
		super.onEnabled(context);
	}

	/**
	 * 当你的App Widget的最后一个实例被从宿主中删除时被调用。你应该在onEnabled(Context)中做一些清理工作,
	 * 比如删除一个临时的数据库
	 */
	@Override
	public void onDisabled(Context context) {
		System.out.println("onDisabled");
		super.onDisabled(context);
	}

	/**
	 * 接收到每个广播时都会被调用,而且在上面的回调函数之前。 你通常不需要实现这个方法,因为缺省的AppWidgetProvider实现过滤所有App
	 * Widget广播并恰当的调用上述方法。 注意: 在Android 1.5中,有一个已知问题,onDeleted()方法在调用时不被调用。
	 * 为了规避这个问题,你可以像Group post中描述的那样实现onReceive()来接收这个onDeleted()回调。
	 */
	@Override
	public void onReceive(Context context, Intent intent) {
		System.out.println("onReceive");
		super.onReceive(context, intent);
	}
}

 2.定义桌面上显示的Widget布局文件,新建xml文件my_layout代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="150dip"
    android:layout_height="72dip"
    android:orientation="vertical"
    android:background="#ffffff" >

    <RelativeLayout
        android:id="@+id/search_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#AA3fbbff"
         >

        <ImageView
            android:id="@+id/imageicon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="5dip"
            android:src="@drawable/ic_launcher" />

        <ImageView
            android:id="@+id/editText1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@+id/search"
            android:layout_toRightOf="@+id/imageicon"
            android:focusable="false"
            android:padding="10dip" />

        <Button
            android:id="@+id/search"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="5dip"
            android:background="@drawable/ic_launcher"
            android:padding="10dip"
            android:text="搜索"
            android:textColor="#ffffff"
            android:textSize="16dp" />
    </RelativeLayout>
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center" />

    <Button
        android:id="@+id/btn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/ic_launcher"
        android:gravity="center" />

</LinearLayout>


3.在src文件夹下新建xml文件夹目录,在该目录下新建xml文件,命名为appwidget.xml,代码如下:

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

4.在AndroidManifest.xml文件中添加receive广播接收器代码如下:

<receiver
            android:name=".ExampleAppWidgetProvider"
            android:label="添加桌面控件示例" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

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


5.总结如下:通过上面这四个步骤Widget已经成功添加了,你可以运行程序到桌面上去添加桌面控件就会看到我们刚刚加的“添加桌面控件例子”,点击它就会看见自己写的的Widget。

通过做AppWidget的一些心得总结:
1.在AppWidget中有些控件是不支持的比如说EditText,滑动控件等一些用户需要交互的控件。
2.如果监听Widget中的控件响应事件的话,必须在清单文件中的receive里面注册每个控件的action,然后在ExampleAppWidgetProvider 类的Intent中添加对应的action name就可以了,然后在onReceive方法中判断对应的事件就可以了。示例代码如下

(1).

<intent-filter>
                <action android:name="com.yaodian.activity.widget_left" />
                <action android:name="com.yaodian.activity.widget_right" />
                <action android:name="com.yaodian.activity.widget_search" />
                <action android:name="com.yaodian.activity.widget_voicesearch" />
                <action android:name="com.yaodian.activity.widget_image" />
            </intent-filter>

(2).

private final static String ONCLICK_LEFT = "com.yaodian.activity.widget_left";//左边按钮的action
private final static String ONCLICK_RIGHT = "com.yaodian.activity.widget_right";//右边按钮的action
private final static String ONCLICK_IMAGE = "com.yaodian.activity.widget_image";//图片的action

Intent intent_left = new Intent(ONCLICK_LEFT);//左边按钮呢的Intent
		Intent intent_right = new Intent(ONCLICK_RIGHT);//右边按钮的Intent
		Intent intent_image = new Intent(ONCLICK_IMAGE);//图片的Intent

(3).onReceive方法中

if (intent.getAction().equals(ONCLICK_LEFT)) {//左边按钮的事件响应
} else if (intent.getAction().equals(ONCLICK_RIGHT)) {//右边按钮的事件响应
} else if (intent.getAction().equals(ONCLICK_IMAGE)) {//点击图片跳转到资讯详情页
}

3.如果要点击某个控件跳转到对应的Activity里,可以这样写:

Intent intent_search = new Intent(context, XXX.class);

如果要在对应的intent中传递参数到对应的Activity这可以PendingIntent pendingIntent_search = PendingIntent.getActivity(context, 0, intent_search, PendingIntent.FLAG_UPDATE_CURRENT);最后一个参数的介绍:

int FLAG_CANCEL_CURRENT:如果该PendingIntent已经存在,则在生成新的之前取消当前的。

int FLAG_NO_CREATE:如果该PendingIntent不存在,直接返回null而不是创建一个PendingIntent.

int FLAG_ONE_SHOT:该PendingIntent只能用一次,在send()方法执行后,自动取消。

int FLAG_UPDATE_CURRENT:如果该PendingIntent已经存在,则用新传入的Intent更新当前的数据。


8.

9.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值