我目前正在为我的 android 设备开发一个自制的电池小部件。它只是和 ImageView 和一个 TextView 以百分比显示电池电量。
实际上一切正常,除了不知何故(比如 1 小时,也许 2 小时)后,我用来收听电池变化的广播接收器停止工作,并且我的 UI 不再以正确的百分比水平更新。这可能是什么原因?
此外,我认识到即使接收器停止接收并且 UI 不再更新,服务仍在运行。
这是我的小部件类:
public class BatteryWidgetHD extends AppWidgetProvider {
private static BatteryController bctrl;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
if(bctrl == null) bctrl = new BatteryController(context, appWidgetManager, appWidgetIds);
Log.i("BatteryWidgetHD", "OnUpdate... starting service...");
Intent batteryServiceIntent = new Intent(context.getApplicationContext(), BatteryMonitoringService.class);
context.getApplicationContext().startService(batteryServiceIntent);
}
/**
* service that keeps the broadcastreceiver alive that listens for battery changes
* @author philipp
*
*/
public static class BatteryMonitoringService extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
if(bctrl != null) bctrl.listenToBatteryStatus();
}
@Override
public void onDestroy() {
if(bctrl != null) bctrl.stopListeningToBatteryStatus();
}
}
}
还有我的电池控制器类,它有一个广播接收器并更新用户界面 onReceive():
public class BatteryController {
private int status, level;
private boolean isCharging, isUSBPlugged, isACPlugged;
private Context c;
private BatteryStatusReceiver bsr;
private RemoteViews remoteViews;
private AppWidgetManager appWidgetManager;
private ComponentName thisWidget;
/** constructor
* @param appWidgetManager */
public BatteryController(Context c, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
this.c = c;
this.appWidgetManager = appWidgetManager;
remoteViews = new RemoteViews(c.getPackageName(), R.layout.battery_widget_layout);
thisWidget = new ComponentName(c, BatteryWidgetHD.class);
bsr = new BatteryStatusReceiver();
}
/**
* start listening to broadcasts concerning the battery
*/
public void listenToBatteryStatus() {
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
c.getApplicationContext().registerReceiver(bsr, ifilter);
getStartupBatteryLevel();
}
/**
* stop listening to battery broadcasts
*/
public void stopListeningToBatteryStatus() {
c.getApplicationContext().unregisterReceiver(bsr);
}
private void updateUI() {
remoteViews.setTextViewText(R.id.tvBatteryLevel, "\n" + level + "%");
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
/**
* this class is responsible for listening to broadcasts concerning the
* battery status
*/
private class BatteryStatusReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;
int isPlugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
isUSBPlugged = isPlugged == BatteryManager.BATTERY_PLUGGED_USB;
isACPlugged = isPlugged == BatteryManager.BATTERY_PLUGGED_AC;
// inform the UI about battery changes
updateUI();
Log.i("BatteryController", "BATTERY STATUS CHANGED. Level: " + level + ", Charging: " + isCharging);
// Toast.makeText(c, "Battery status changed.", Toast.LENGTH_SHORT).show();
}
}
}
和 widget_provider.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/battery_widget_layout"
android:minHeight="100dip"
android:minWidth="60dip"
android:previewImage="@drawable/battery75"
android:widgetCategory="keyguard|home_screen"
android:updatePeriodMillis="0" />