Android 已调用广播接收器但未启动前台服务
Android broadcast reciever called but doesn't starts foreground service
我设置了广播接收器以在重启后重新启动我的前台服务。
我有两台设备,可以在 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, 15, TimeUnit.MINUTES, 2, TimeUnit.MINUTES
).build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
TrackerRestartWorker.TAG,
ExistingPeriodicWorkPolicy.REPLACE,
restartTrackerRequest);
}
private void addNotificationAndStartForeground() {
String name = getString(R.string.app_name);
String description = "Service running...";
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, 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"
我设置了广播接收器以在重启后重新启动我的前台服务。
我有两台设备,可以在 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, 15, TimeUnit.MINUTES, 2, TimeUnit.MINUTES
).build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
TrackerRestartWorker.TAG,
ExistingPeriodicWorkPolicy.REPLACE,
restartTrackerRequest);
}
private void addNotificationAndStartForeground() {
String name = getString(R.string.app_name);
String description = "Service running...";
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, 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"