什么是AppWidget?AppWidget就是我们平常在桌面上见到的那种一个个的小窗口,利用这个小窗口可以给用户提供一些方便快捷的操作。
现在我们就结合AppWidget来写一个娱乐小应用:警报器。半夜三更,你独自一人走在一条盲肠小道里,突然你发现后面有一个猥琐的身影跟了你一会儿了,这时你听见那人加快了脚步冲你走来,周围一个人也没有,拖着劳累了一天疲惫身体的你显然跑不过他,砰砰...砰砰....他越走越快,突然你把手伸进了口袋里,就在这千钧一发之际周围响起了警笛声,那人见事态不妙就立刻掉转了身头。对!没错!!!就是因为使用了它,这款警报器应用才能幸免于难,还等什么呢?大家一起来学习学习吧。(这广告.....)
其实它很简单,是通过安装一个Appwidget(小部件)在桌面上,直接点击按钮就能发出警报声。
通过添加小部件Alarm1,得到一个如下的控件,给大家有个整体的印象:
项目结构图:
我们开始吧
1,首先在res文件夹下新建一个名字为xml的文件夹,然后在xml目录下创建一个名为widget_provider的xml文件(如上图所示)。内容如下:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/desk"
android:minHeight="72dp"
android:minWidth="72dp"
android:updatePeriodMillis="86400000" >
</appwidget-provider>
这个xml是用来描述你所要创建的appWidget的一些描述信息的,比如高度、宽度、刷新间隔、布局文件等等。仅仅这个描述文件还不够,我们看到的appWidget可都是有界面元素的呀,比如说文本,图片,按钮等等,这些东西的定义都需要放到layout文件夹下面。这个文件就是上面代码中写到的那个desk.xml。
2,在layout文件夹下面新建一个desk.xml文件,在这个文件中描述了appWidget的控件和布局等等信息,就和我们平常创建的一个activity的布局文件没什么两样,就一个ImageButton。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="vertical" >
<ImageButton
android:id="@+id/alarmbt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/alarm_blue" />
</LinearLayout>
3, 既然appWidget中存在按钮等等控件,那么就肯定少不了处理这些控件事件的处理代码啦。这些代码被放在一个继承于AppWidgetProvider的类中,在本例子中我新建了一个myProvider的类,该类继承于AppWidgetProvider,以后所有的AppWidget上面的控件事件都会在这个类中处理。看一下类的内容:
package sina.CreAmazing.alarm;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.widget.RemoteViews;
public class myProvider extends AppWidgetProvider {
//状态量判断警报器是否开启
private static boolean on = false;
//用于指定intent的Action值
private static final String UPDATE_ACTION = "sina.CreAmazing.alarm";
//MediaPlayer用于播放存在res/raw/alarm.mp3文件
private static MediaPlayer mp;
@Override
public void onEnabled(Context context) {
// TODO Auto-generated method stub
super.onEnabled(context);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
//当有多个控件时此方法用于对每个控件的更新
for (int i = 0; i < appWidgetIds.length; i++) {
Intent intent = new Intent();
intent.setAction(UPDATE_ACTION);
PendingIntent pi = PendingIntent
.getBroadcast(context, 0, intent, 0);
RemoteViews rv = new RemoteViews(context.getPackageName(),
R.layout.desk);
//为AppWidget绑定监听器(PendingIntent)
rv.setOnClickPendingIntent(R.id.alarmbt, pi);
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
@Override
public void onDisabled(Context context) {
// TODO Auto-generated method stub
super.onDisabled(context);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onDeleted(context, appWidgetIds);
}
//重要方法,用于接收广播
@Override
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
//确定是自己发出广播时,执行图片的变换和警笛声音的播放
if (action.equals(UPDATE_ACTION)) {
RemoteViews rv = new RemoteViews(context.getPackageName(),
R.layout.desk);
//如果是开启的,就关闭
if (on) {
rv.setImageViewResource(R.id.alarmbt, R.drawable.alarm_blue);
on = false;
//停止MediaPlayer的播放
stopAlarm(context);
//如果是关闭的就开启
} else if (!on) {
rv.setImageViewResource(R.id.alarmbt, R.drawable.alarm_red);
on = true;
//新开一个线程进行播放
new Thread() {
@Override
public void run() {
startAlarm(context);
super.run();
}
}.start();
}
//进行更新
ComponentName componentName = new ComponentName(context,
myProvider.class);
AppWidgetManager am = AppWidgetManager.getInstance(context);
am.updateAppWidget(componentName, rv);
}
super.onReceive(context, intent);
}
private void stopAlarm(Context context) {
mp.stop();
mp.release();
}
private void startAlarm(Context context) {
mp = MediaPlayer.create(context, R.raw.alarm);
mp.start();
}
}
4, 在AndroidManifest.xml中定义一些创建AppWidget必要的东西,先看代码:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="sina.CreAmazing.alarm" android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Alarm1Activity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".myProvider">
<intent-filter >
<action android:name="sina.CreAmazing.alarm"/>
</intent-filter>
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_provider" />
</receiver>
</application>
</manifest>
主要就是为myProvider注册一个intent—filter。
最后是效果图:
这是关闭时:
这是开启时的:
因为该应用稍微有点繁琐,知识点有点多,可能不大适合初学者这里有一篇介绍AppWidget比较详细:
点击打开链接可以先看看这篇,再来这里看看,其实两篇差异不大,也就是在MediaPlayer的使用上。只要仔细看看官方文档里MediaPlayer的使用说明就能明白。