我试图用一个开关按钮启动和停止服务,但一旦服务启动,它就会执行任务,当开关按钮关闭时,它不会执行stopservice();
从mainactivity内的共享首选项(sharedpref.getisautochange())检索开关按钮的状态
if (sharedPref.getIsAutoChange()) {
startService();
Log.d(TAG, "Service Started");
} else {
stopService();
Log.d(TAG, "Service Stopped");
}
mainactivity中的方法
public void startService() {
Log.d(TAG, "startService called");
if (!MyService.isServiceRunning) {
Intent serviceIntent = new Intent(this, MyService.class);
ContextCompat.startForegroundService(this, serviceIntent);
//startService(serviceIntent);
}
}
public void stopService() {
Log.d(TAG, "stopService called");
if (MyService.isServiceRunning) {
Intent serviceIntent = new Intent(this, MyService.class);
stopService(serviceIntent);
}
}
public void startServiceViaWorker() {
Log.d(TAG, "startServiceViaWorker called");
String UNIQUE_WORK_NAME = "StartMyServiceViaWorker";
//String WORKER_TAG = "MyServiceWorkerTag";
WorkManager workManager = WorkManager.getInstance(this);
// As per Documentation: The minimum repeat interval that can be defined is 15 minutes (
// same as the JobScheduler API), but in practice 15 doesn't work. Using 16 here
PeriodicWorkRequest request =
new PeriodicWorkRequest.Builder(
MyWorker.class,
16,
TimeUnit.MINUTES)
//.addTag(WORKER_TAG)
.build();
workManager.enqueueUniquePeriodicWork(UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, request);
我的接收器
public class MyReceiver extends BroadcastReceiver {
private String TAG = "MyReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive called");
//ContextCompat.startForegroundService(context, new Intent(context, MyService.class));
// We are starting MyService via a worker and not directly because since Android 7
// (but officially since Lollipop!), any process called by a BroadcastReceiver
// (only manifest-declared receiver) is run at low priority and hence eventually
// killed by Android.
WorkManager workManager = WorkManager.getInstance(context);
OneTimeWorkRequest startServiceRequest = new OneTimeWorkRequest.Builder(MyWorker.class)
.build();
workManager.enqueue(startServiceRequest);
}
}
我的服务
public class MyService extends Service {
private String TAG = "MyService";
public static boolean isServiceRunning;
private String CHANNEL_ID = "NOTIFICATION_CHANNEL";
private ScreenLockReceiver screenLockReceiver;
private Timer timer;
public MyService() {
Log.d(TAG, "constructor called");
isServiceRunning = false;
screenLockReceiver = new ScreenLockReceiver();
timer = new Timer();
}
public void terminateService(){
this.stopSelf();
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate called");
createNotificationChannel();
isServiceRunning = true;
// register receiver to listen for screen on events
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenLockReceiver, filter);
// a dummy timer task - can be ignored
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Log.d(TAG, "run called inside scheduleAtFixedRate");
}
}, 0, PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand called");
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Service is Running")
.setContentText("Listening for Screen Off/On events")
.setSmallIcon(R.drawable.ic_stat_onesignal_default)
.setContentIntent(pendingIntent)
.setColor(getResources().getColor(R.color.colorPrimary))
.build();
/*
* A started service can use the startForeground API to put the service in a foreground state,
* where the system considers it to be something the user is actively aware of and thus not
* a candidate for killing when low on memory.
*/
startForeground(1, notification);
// does not work as expected though, even START_NOT_STICKY gives same result
// device specific issue?
return START_STICKY;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String appName = getString(R.string.app_name);
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
appName,
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy called");
isServiceRunning = false;
stopForeground(true);
// unregister receiver
unregisterReceiver(screenLockReceiver);
// cancel the timer
if (timer != null) {
timer.cancel();
}
// call MyReceiver which will restart this service via a worker
Intent broadcastIntent = new Intent(this, MyReceiver.class);
sendBroadcast(broadcastIntent);
super.onDestroy();
}
// Not getting called on Xiaomi Redmi Note 7S even when autostart permission is granted
@Override
public void onTaskRemoved(Intent rootIntent) {
Log.d(TAG, "onTaskRemoved called");
super.onTaskRemoved(rootIntent);
}
@Override
public boolean stopService(Intent name) {
// TODO Auto-generated method stub
timer.cancel();
return super.stopService(name);
}
}
我的工人
public class MyWorker extends Worker {
private final Context context;
private String TAG = "MyWorker";
public MyWorker(
@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
this.context = context;
}
@NonNull
@Override
public Result doWork() {
Log.d(TAG, "doWork called for: " + this.getId());
Log.d(TAG, "Service Running: " + MyService.isServiceRunning);
if (!MyService.isServiceRunning) {
Log.d(TAG, "starting service from doWork");
Intent intent = new Intent(this.context, MyService.class);
/*
* startForegroundService is similar to startService but with an implicit promise
* that the service will call startForeground once it begins running.
* The service is given an amount of time comparable to the ANR interval to do this,
* otherwise the system will automatically stop the service and declare the app ANR.
*/
ContextCompat.startForegroundService(context, intent);
//this.context.startService(intent);
}
return Result.success();
}
@Override
public void onStopped() {
Log.d(TAG, "onStopped called for: " + this.getId());
super.onStopped();
}
屏幕锁接收器:监测检查解锁状态(每当屏幕解锁时,我都会使用该服务更改壁纸)
public class ScreenLockReceiver extends BroadcastReceiver {
private String TAG = "ScreenLockReceiver";
@Override
public void onReceive(Context context, Intent intent) {
// This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_ON)) {
Log.d(TAG, "onReceive called: screen on");
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Log.d(TAG, "onReceive called: screen off");
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
Log.d(TAG, "onReceive called: screen unlocked");
new Utils().setRandomWallpaper(context);
}
}
}
在舱单里面
<receiver
android:name=".services.MyReceiver"
android:enabled="true"
android:exported="false" />
<service
android:name=".services.MyService"
android:process=":MyService"
android:enabled="true"
android:exported="false" />
请帮我解决这个问题。
暂无答案!
目前还没有任何答案,快来回答吧!