问题描述
我设置了广播接收器,以便在重新启动后重新启动前台服务。
我有两个设备,它可以在Meizu M1 note (android 5.1)
上运行,但是不能在Samsung A8 (android 9)
上运行。在Oreo
之后的限制中寻找原因,似乎还可以,但以防万一https://developer.android.com/about/versions/oreo/background.html
在第二个广播接收器上呼叫,但是重新启动后服务未启动。
服务跟踪位置,并将startForeground()
与Notification
一起使用以进行正确的工作。
还尝试添加Worker
以便在重新启动后重新启动服务,但此后似乎缺少工作。
请给我任何建议,以使我的收信人无法运行服务。
谢谢。
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tracker">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".ui.di.App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:isolatedProcess="true"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver android:name="com.example.tracker.ui.broadcast.ServiceRestart">
<intent-filter>
<action android:name="restartService" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service
android:name="com.example.tracker.ui.service.TrackerService"
android:enabled="true" />
<service
android:name="com.example.tracker.ui.worker.RestartIntentService"
android:enabled="true" />
<activity android:name=".ui.screen.main.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
收件人:
public class ServiceRestart extends BroadcastReceiver {
@Override
public void onReceive(Context context,Intent intent) {
Log.i("Broadcast Listened","Service tried to stop");
Toast.makeText(context,"Broadcast: ServiceRestart launched " + intent.getAction(),Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context,TrackerService.class));
} else {
context.startService(new Intent(context,TrackerService.class));
}
}
}
服务:
public class TrackerService extends Service implements LocationListener {
public static final String TAG = "TrackerService";
private static final int PROCESS_ID = 1024;
private static final int INTERVAL = 120; //seconds
private ConnectivityManager connectivityManager;
private PeriodicWorkRequest workRequest;
private PeriodicWorkRequest restartTrackerRequest;
private DbFirebaseModel dbFirebaseModel = new DbFirebaseModel();
private ServiceHandler mServiceHandler;
private static final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message message) {
}
}
public void onCreate() {
super.onCreate();
HandlerThread mHandlerThread = new HandlerThread("TrackerService.HandlerThread");
mHandlerThread.start();
mServiceHandler = new ServiceHandler(mHandlerThread.getLooper());
}
public TrackerService() {
super();
}
@Override
public int onStartCommand(Intent intent,int flags,int startId) {
super.onStartCommand(intent,flags,startId);
addNotificationAndStartForeground();
addWorkers();
mServiceHandler.post(() -> {
connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
runLocationTransfer();
});
Log.d(TAG,"===== SERVICE START");
return START_STICKY;
}
private void addWorkers() {
workRequest = new PeriodicWorkRequest.Builder(
FirebaseWorker.class,15,TimeUnit.MINUTES,2,TimeUnit.MINUTES)
.build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
FirebaseWorker.TAG,ExistingPeriodicWorkPolicy.REPLACE,workRequest);
restartTrackerRequest = new PeriodicWorkRequest.Builder(
TrackerRestartWorker.class,TimeUnit.MINUTES
).build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
TrackerRestartWorker.TAG,restartTrackerRequest);
}
private void addNotificationAndStartForeground() {
String name = getString(R.string.app_name);
String description = "Service running...";
PendingIntent pendingIntent = PendingIntent.getActivity(this,new Intent(this,MainActivity.class),0);
Notification.Builder notificationBuilder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
Integer.toString(PROCESS_ID),"Tracker",NotificationManager.IMPORTANCE_HIGH);
channel.setDescription("Notify me when location tracking");
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
notificationBuilder = new Notification.Builder(this,Integer.toString(PROCESS_ID));
notificationBuilder.setContentTitle(name)
.setContentText(description)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent);
notificationManager.notify(PROCESS_ID,notificationBuilder.build());
} else {
notificationBuilder = new Notification.Builder(this);
notificationBuilder.setContentTitle(name)
.setContentText(description)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent);
}
startForeground(PROCESS_ID,notificationBuilder.build());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG,"===== SERVICE STOP");
if (FirebaseAuth.getInstance().getCurrentUser() == null) {
WorkManager.getInstance(this).cancelWorkById(workRequest.getId());
WorkManager.getInstance(this).cancelWorkById(restartTrackerRequest.getId());
Log.d(TAG,"===== WORKERS STOP");
}
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Log.d(TAG,"TASK REMOVED");
Toast.makeText(this,"LOCATION TASK REMOVED",Toast.LENGTH_SHORT).show();
super.onTaskRemoved(rootIntent);
}
private void runLocationTransfer() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
locationRequest.setInterval(INTERVAL * 1000);
locationRequest.setFastestInterval(INTERVAL * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(locationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
settingsClient.checkLocationSettings(locationSettingsRequest);
try {
getFusedLocationProviderClient(this).requestLocationUpdates(locationRequest,new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
onLocationChanged(locationResult.getLastLocation());
}
},Looper.myLooper());
} catch (SecurityException e) {
e.printStackTrace();
}
}
@Override
public void onLocationChanged(@NonNull Location location) {
if (FirebaseAuth.getInstance().getCurrentUser() == null) {
stopSelf();
Log.d(TAG,"====== SERVICE STOPPED by itself");
} else if (connectivityManager.getActiveNetworkInfo() != null
&& connectivityManager.getActiveNetworkInfo().isConnected()) {
dbFirebaseModel.saveLocation(location);
// test using sound notifications
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(),notification);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(this,"LOCATION ------ LATITUDE: " + location.getLatitude() + " LONGITUDE: " + location.getLongitude(),Toast.LENGTH_SHORT).show();
} else {
saveToLocalStorage(location);
}
}
private void saveToLocalStorage(Location location) {
Hawk.init(this).build();
String userId = Objects.requireNonNull(
FirebaseAuth.getInstance().getCurrentUser()
).getUid();
LocationData locationData = new LocationData(userId,location);
long count = 0;
if (Hawk.count() > count) {
count = Hawk.count();
}
while (Hawk.contains(String.valueOf(count))) {
count++;
}
Hawk.put(String.valueOf(count),locationData);
Log.d(TAG,"HAWK /// Saved to local storage. COUNT = " + Hawk.count());
}
}
解决方法
以下步骤可以帮助我解决问题:
-
删除并重新安装应用
-
根据此更改
manifest
<receiver android:name="com.foxminded.tracker.ui.broadcast.ServiceRestart" android:exported="true" android:enabled="true"> <intent-filter> <action android:name="restartService" /> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
此处添加了"android.intent.action.LOCKED_BOOT_COMPLETED"
和android:exported="true" android:enabled="true"