问题描述
我有一个定位服务,可以在Firestore中添加/更新数据。打开应用程序后,它可以正常工作,但是如果我强制关闭应用程序或切换到另一个应用程序,则该服务将不再起作用。我在Realme 3专业版设备上对此进行了测试。
- 即使在应用程序管理器中关闭了应用程序,也要运行服务。
服务等级
public class LocationService extends Service {
private static final String TAG = "SERVICE";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 0;
private static final float LOCATION_disTANCE = 0;
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
public LocationListener(String provider) {
Log.e(TAG,"LocationListener " + provider);
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location) {
mLastLocation.set(location);
}
@Override
public void onProviderdisabled(String provider) {
Log.e(TAG,"onProviderdisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.e(TAG,"onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider,int status,Bundle extras) {
Log.e(TAG,"onStatusChanged: " + provider);
}
}
LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),new LocationListener(LocationManager.NETWORK_PROVIDER)
};
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent,int flags,int startId) {
Log.e(TAG,"onStartCommand");
super.onStartCommand(intent,flags,startId);
LocationInitialize();
return START_STICKY;
}
@Override
public void onCreate() {
Log.e(TAG,"onCreate");
}
public void LocationInitialize(){
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,LOCATION_INTERVAL,LOCATION_disTANCE,mLocationListeners[1]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG,"fail to request location update,ignore",ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG,"network provider does not exist," + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG,"gps provider does not exist " + ex.getMessage());
}
}
@Override
public void onDestroy() {
Log.e(TAG,"onDestroy");
super.onDestroy();
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this,RestartService.class);
this.sendbroadcast(broadcastIntent);
}
private void initializeLocationManager() {
Log.e(TAG,"initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
@Override
public void onTaskRemoved( Intent rootIntent ) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this,RestartService.class);
this.sendbroadcast(broadcastIntent);
}
}
广播接收
public class RestartService extends broadcastReceiver {
@Override
public void onReceive(Context context,Intent intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context,LocationService.class));
} else {
context.startService(new Intent(context,LocationService.class));
}
}
}
Android清单
<receiver
android:name=".service.RestartService"
android:enabled="true"
android:stopWithTask="false"
android:exported="true">
<intent-filter>
<action android:name="restartservice" />
</intent-filter>
</receiver>
<service
android:name=".service.LocationService"
android:enabled="true"
android:exported="true" />
解决方法
根据Google Developer最近的政策,您不应该使用 基于清单的广播接收器,尽管它不能在26以上运行 SDK
https://developer.android.com/guide/components/broadcasts#changes-system-broadcasts
因此无需使用广播接收器即可重新启动服务。
使用此代码重新启动服务
更新的服务等级
public class LocationService extends Service {
private static final String TAG = "SERVICE";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 0;
private static final float LOCATION_DISTANCE = 0;
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
public LocationListener(String provider) {
Log.e(TAG,"LocationListener " + provider);
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location) {
mLastLocation.set(location);
}
@Override
public void onProviderDisabled(String provider) {
Log.e(TAG,"onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.e(TAG,"onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider,int status,Bundle extras) {
Log.e(TAG,"onStatusChanged: " + provider);
}
}
LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),new LocationListener(LocationManager.NETWORK_PROVIDER)
};
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent,int flags,int startId) {
Log.e(TAG,"onStartCommand");
super.onStartCommand(intent,flags,startId);
LocationInitialize();
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startMyOwnForeground();
} else {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,"1");
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("My service.")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(1,notification);
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void startMyOwnForeground() {
String channelName = "My service";
NotificationChannel chan = new NotificationChannel("2",channelName,NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,"2");
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("My service")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2,notification);
}
public void LocationInitialize(){
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,LOCATION_INTERVAL,LOCATION_DISTANCE,mLocationListeners[1]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG,"fail to request location update,ignore",ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG,"network provider does not exist," + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG,"gps provider does not exist " + ex.getMessage());
}
}
@Override
public void onDestroy() {
Log.e(TAG,"onDestroy");
super.onDestroy();
// no need to do anything here
//Intent broadcastIntent = new Intent();
//broadcastIntent.setAction("restartservice");
//broadcastIntent.setClass(this,RestartService.class);
//this.sendBroadcast(broadcastIntent);
}
private void initializeLocationManager() {
Log.e(TAG,"initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(),this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(),1,restartServiceIntent,PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime() + 1000,restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
}