androidの桌面小控件—电池状态显示
1 . 桌面控件介绍
桌面小控件的实现是基于Broadcast的形式实现的,因此,每一个桌面小控件都对应于一个BroadcastReceiver类。Android系统提供了一个AppWidgetProvider类(它就是BroadcastReceiver的子类),这个类很关键,你在写桌面小控件时只需继承这个类就行。继承了AppWidgetProvider类之后,你可以根据自己的需要覆盖它的不同的生命周期的方法,来达到自己的目的。AppWidgetProvider类的主要提供如下不同生命周期的方法:
void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) { }
// 这个方法字面意思是负责更新桌面小控件,但貌似只有在小控件被用户放到桌面上时被调用了一次,读者可以自己通过输出Log来测试
// 实现桌面控件是通常都会考虑重写该方法
void onDeleted(Context context, int[] appWidgetIds)
// 在小控件被删除时调用该方法
void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) { }
// 这个方法字面意思是负责更新桌面小控件,但貌似只有在小控件被用户放到桌面上时被调用了一次,读者可以自己通过输出Log来测试
// 实现桌面控件是通常都会考虑重写该方法
void onDeleted(Context context, int[] appWidgetIds)
// 在小控件被删除时调用该方法
一般来说,开发桌面小控件只需要定义一个AppWidgetProvider的子类,并重新写它的pnUpdate方法即可。
2. 示例讲解
public class AppWidet extends AppWidgetProvider {
private static int currentBatteryLevel;
private static int currentBatteryStatus;
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
// 启动自动更新电池信息的service
context.startService(new Intent(context, updateService.class));
//为AppWidget设置点击事件的响应,启动显示电池信息详情的activity
Intent startActivityIntent = new Intent(context,BatteryInfoActivity.class);
PendingIntent Pintent = PendingIntent.getActivity(context, 0,startActivityIntent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.other_layout);
views.setOnClickPendingIntent(R.id.imageView, Pintent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
// 自动更新电池信息的service ,通过AlarmManager 实现定时不间断的发送电池信息
public static class updateService extends Service {
// 定义机器人图片
Bitmap bmp;
@Override
public IBinder onBind(Intent intent) {
return null;
}
// 定义一个接受电池信息的broadcastReceiver
private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 获取当前电量
currentBatteryLevel = intent.getIntExtra("level", 0);
// 获取当前电池状态
// 电池状态,返回是一个数字
// BatteryManager.BATTERY_STATUS_CHARGING 表示是充电状态
// BatteryManager.BATTERY_STATUS_DISCHARGING 放电中
// BatteryManager.BATTERY_STATUS_NOT_CHARGING 未充电
// BatteryManager.BATTERY_STATUS_FULL 电池满
currentBatteryStatus = intent.getIntExtra("status", 0);
}
};
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
// 注册监听电池信息广播
registerReceiver(batteryReceiver, new IntentFilter(
Intent.ACTION_BATTERY_CHANGED));
// 定义一个AppWidgetManager对象
AppWidgetManager manager = AppWidgetManager.getInstance(this);
// 定义一个RemoteViews,实现对AppWidget的控制
RemoteViews views = new RemoteViews(getPackageName(),
R.layout.other_layout);
// 当正在充电或充满电时,显示充电的图片
if (currentBatteryStatus == 2 || currentBatteryStatus == 5) {
.......
} else { // 未进行充电
.......
}
// 设置AppWidget上显示的图片和文字的内容
views.setImageViewBitmap(R.id.imageView, bmp);
views.setTextViewText(R.id.tv, currentBatteryLevel + "%");
// 将AppWidgetProvider子类实例包装成ComponentName对象
ComponentName thisWidget = new ComponentName(this, AppWidet.class);
// 使用AlarmManager实现每隔一秒发送一次更新提示信息,实现信息实时动态变化
long now = System.currentTimeMillis();
long pause = 1000;
Intent alarmIntent = new Intent();
alarmIntent = intent;
PendingIntent pendingIntent = PendingIntent.getService(this, 0,
alarmIntent, 0);
// 定时发送更新提示
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, now + pause, pendingIntent);
manager.updateAppWidget(thisWidget, views);
}
}
}
然后是点击桌面插件显示界面。
public class BatteryInfoActivity extends Activity {
..........
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置activity无标题
setContentView(R.layout.main_layout); // 使用newlayout的布局
tvBatteryStatus = (TextView) findViewById(R.id.tvBatteryStatus);
tvBatteryLevel = (TextView) findViewById(R.id.tvBatteryLevel);
tvBatteryHealth = (TextView) findViewById(R.id.tvBatteryHealth);
tvBatteryTemperature = (TextView) findViewById(R.id.tvBatteryTemperature);
tvBatteryVoltage = (TextView) findViewById(R.id.tvBatteryVoltage);
tvBatteryTechnology = (TextView) findViewById(R.id.tvBatteryTechnology);
flag = true; // 提示service的标志位置为true
infoReceiver = new BroadcastReceiver() // 提示信息接收器的定义
{
@Override
public void onReceive(Context context, Intent intent) {
setText(); //收到intent,就及时修改TextView信息,使得Activity显示时,电池信息也能动态显示
}
};
//注册提示信息的intentFilter
IntentFilter filter = new IntentFilter();
filter.addAction("com.wyl.example.broadcast");
registerReceiver(infoReceiver, filter);
// 启动提示service
Intent startService = new Intent(this, updateService.class);
startService(startService);
}
//点击屏幕任意位置,关闭电池信息Activity
public boolean onTouchEvent(MotionEvent event) {
this.finish();
return true;
}
@Override
protected void onDestroy() {
flag = false;
unregisterReceiver(infoReceiver);
super.onDestroy();
}
//及时动态修改Activity上文字信息的函数
public static void setText() {
。。。。
}
/** 提示信息变化的service,约每隔一秒,就发送intent,
* 提醒activity更新电池信息,主要为了检测电池状态的变化,
* 例如连上充电时,状态会从“未在充电”变为“正在充电”
* 通过调用plugged方式,还能判断是AC方式充电还是USB方式充电
*/
public static class updateService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
/** 定义得到电池信息的BroadcastReceiver,提取出关键信息,存入变量中 */
private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
currentBatteryStatus = intent.getIntExtra("status", 0);
currentBatteryLevel = intent.getIntExtra("level", 0);
currentBatteryHealth = intent.getIntExtra("health", 0);
currentBatteryTemperature = intent
.getIntExtra("temperature", 0);
currentBatteryVoltage = intent.getIntExtra("voltage", 0);
currentBatteryTechnology = intent.getStringExtra("technology");
currentBatteryPlugged = intent.getIntExtra("plugged", 0);
}
};
public void onStart(Intent intent, int startId) {
registerReceiver(batteryReceiver, new IntentFilter(
Intent.ACTION_BATTERY_CHANGED));
/** 启动一个线程,约每隔一秒就发送intent提醒Activity更新电池信息 */
new Thread() {
public void run() {
while (flag) {
Intent sendInfoToActivity = new Intent();
sendInfoToActivity
.setAction("com.wyl.example.broadcast");
sendBroadcast(sendInfoToActivity);
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}.start();
super.onStart(intent, startId);
}
}
}