想写一个根据电量来切换图片的AppWidget,由于监视电量需要另起一个service,我的想法是在添加第一个widget时启动service,在删除最后一个时结束service。
layout
<?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">
<ImageView
android:id="@+id/container_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
manifest.xml
<service
android:name=".HelloService"></service>
<receiver android:name=".HelloWorld">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/hello_world_info" />
</receiver>
AppWidgetProvider代码如下:
/**
* 广播接收器
*/
public class HelloWorld extends AppWidgetProvider {
private static String mShuouyang = "shuouyang";
/**
* @param context
* @param appWidgetManager
* @param appWidgetIds 一个桌面程序可能被安放好几个
*/
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
Log.d(mShuouyang, "广播========onUpdate: =======");
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
@Override
public void onEnabled(Context context) {
Log.d(mShuouyang, "广播======== onEnabled: =======");
Intent mIntent = new Intent(context, HelloService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(mIntent);
} else {
context.startService(mIntent);
}
Log.d(mShuouyang, "广播========启动了Service: =======");
// Enter relevant functionality for when the first widget is created
}
@Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
Log.d(mShuouyang, "广播======== onDisabled: =======");
context.stopService(new Intent(context, HelloService.class));//停止service
// context.stopService(mIntent);
}
@Override
public void onReceive(Context context, Intent intent) {
Log.d(mShuouyang, "广播======== onReceive: =======");
super.onReceive(context, intent);
}
}
在service中,注册一个匿名内部类的广播接收器来接收电量后更具电量显示图片
public class HelloService extends Service {
private static BroadcastReceiver mBroadcastReceiver;
public HelloService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
mBroadcastReceiver = new BroadcastReceiver() {
private int[] drawables = {
R.drawable.helloworld0,
R.drawable.helloworld1,
R.drawable.helloworld2,
R.drawable.helloworld3,
R.drawable.helloworld4,
R.drawable.helloworld5,
R.drawable.helloworld6,
R.drawable.helloworld7,
R.drawable.helloworld8,
R.drawable.helloworld9,
R.drawable.helloworld10,
};
int percent = 5;//当前电量标志
int level = 0; //当前电量
int scale = 100;//总电量
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
try {
if (action.equals("android.intent.action.BATTERY_CHANGED")) {
this.level = intent.getExtras().getInt("level", 0);//当前电量
this.scale = intent.getExtras().getInt("scale", 100);//总电量
this.percent = level *10/scale;
Log.d("shuouyang", "服务 onReceive: 获取到了电量信息"+ percent);
}
AppWidgetManager instance = AppWidgetManager.getInstance(context);
ComponentName componentName = new ComponentName(context, HelloWorld.class);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.hello_world);
remoteViews.setImageViewResource(R.id.container_image,drawables[this.percent]);
instance.updateAppWidget(componentName,remoteViews);
Log.d("shuouyang", "服务 onReceive: 逻辑通知完成");
}catch (Exception e){
e.printStackTrace();
Toast.makeText(context,"未获取到电量",Toast.LENGTH_SHORT).show();
}
}
};
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
IntentFilter intentFilter = new IntentFilter("android.intent.action.BATTERY_CHANGED");
registerReceiver(mBroadcastReceiver,intentFilter);//注册接收电量改变的广播接收器
}
@Override
public void onDestroy() {
Log.d("shuouyang", "服务 onDestroy: 服务被销毁");
unregisterReceiver(mBroadcastReceiver);//解除注册
super.onDestroy();
}
}
启动成功
当我将wigget添加到桌面时,开始几秒(通过AVD的外部控制器修改电量)可以根据此时电量显示指定图片和切换图片,后面就切换不了了,只能显示固定的一张图片。查看log显示,service内部的广播接收器在初始几秒就收了几次广播后就自动onDestroy了。不明白是什么停止了服务,
log如下
20-08-19 13:07:50.614 9319-9319/? D/xxxxxx: 广播======== onReceive: =======
2020-08-19 13:07:50.629 9319-9319/? D/xxxxxx: 广播======== onReceive: =======
2020-08-19 13:07:50.629 9319-9319/? D/xxxxxx: 广播========onUpdate: =======
2020-08-19 13:07:50.629 9319-9319/? D/xxxxxx: 广播========启动了Service: =======
2020-08-19 13:07:50.630 9319-9319/? D/xxxxxx: 服务 onReceive: 获取到了电量信息8
2020-08-19 13:07:50.633 9319-9319/? D/xxxxxx: 服务 onReceive: 逻辑通知完成
2020-08-19 13:07:55.327 9319-9319/com.shu.helloworld D/xxxxxx: 服务 onReceive: 获取到了电量信息7
2020-08-19 13:07:55.329 9319-9319/com.shu.helloworld D/xxxxxx: 服务 onReceive: 逻辑通知完成
2020-08-19 13:07:55.620 9319-9319/com.shu.helloworld D/xxxxxx: 服务 onDestroy: 服务被销毁
Android 8.0 还对特定函数做出了以下变更:
startService()
IllegalStateException
Context.startForegroundService()
Context.startForegroundService()
startForeground()
也就是你的服务不正常被干掉了是吧?
你这样子,注释掉你干掉服务的地方。看看是系统干掉的,还是你自己干掉的。