问题
当我在A应用启动一个服务,在服务中开启一个线程, 当我们手动滑动杀死APP时,服务还是活着的,我们希望重新拉起APP应用,我们可能尝试如下代码,有时候可以拉起来,有时候没有任何反应,但是从日志来看,服务运行正常,心跳的日志正常打印。
public class StepService extends Service {
private static final String TAG = "StepService";
public static boolean isRemoveTask = false;
private Handler handler = new Handler(Looper.getMainLooper());
private SvrBinder mBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "<Stub> StepService Connected.");
}
@Override
public void onServiceDisconnected(ComponentName name) {
// Toast.makeText(RemoteService.this,"链接断开,重新启动 LocalService",Toast.LENGTH_LONG).show();
Log.e(TAG, "<Stub> StepService Disconnected.");
// startService(new Intent(StepService.this, GuardService.class));
// bindService(new Intent(StepService.this, GuardService.class), this , Context.BIND_IMPORTANT);
Log.e(TAG, "<Stub> StepService Disconnected end.");
}
};
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "<Stub> StepService onCreate.");
String CHANNEL_ONE_ID = "StepServiceId";
String CHANNEL_ONE_NAME = "StepServiceChannel";
String CHANNEL_ID = "StepServiceChannelId";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager == null)
return;
manager.createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setAutoCancel(true)
.setCategory(Notification.CATEGORY_SERVICE)
.setOngoing(true)
.setPriority(NotificationManager.IMPORTANCE_LOW)
.build();
}
isHeartBeatThread = true;
if (heartBeatThread == null || !heartBeatThread.isAlive()){
heartBeatThread = new HeartBeatThread();
heartBeatThread.start();
}
// startService(new Intent(StepService.this, GuardService.class));
// bindService(new Intent(StepService.this, GuardService.class),connection,Context.BIND_IMPORTANT);
Log.e(TAG, "<Stub> StepService isRemoveTask:" + isRemoveTask);
if (isRemoveTask){
/* Intent intent = new Intent(getBaseContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);*/
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Toast.makeText(this,"RemoteService 启动",Toast.LENGTH_LONG).show();
Log.e(TAG, "<Stub> StepService onStartCommand.");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
mBinder = new SvrBinder();
return mBinder;
}
private HeartBeatThread heartBeatThread;
private boolean isHeartBeatThread;
class HeartBeatThread extends Thread{
@Override
public void run() {
super.run();
while (isHeartBeatThread){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, "HeartBeatThread on on on");
}
}
}
/**
* 用于客户端绑定器的类。因为我们知道这个服务总是运行在与其客户机相同的进程中,
* 所以我们不需要处理IPC。
*/
public class SvrBinder extends IStepServiceAidlInterface.Stub {
@Override
public void keepAlive() throws RemoteException {
Log.e(TAG, "<Stub> StepService keepAlive.");
}
}
@Override
public void onDestroy() {
super.onDestroy();
isHeartBeatThread = false;
unbindService(connection);
Log.e(TAG, "<Stub> StepService onDestroy.");
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
isRemoveTask = true;
Log.e(TAG, "<Stub> StepService onTaskRemoved.");
/* Intent intent = new Intent(getBaseContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);*/
/* Intent intent = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(getBaseContext().getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent restartIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager mgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用*/
Intent k = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(getBaseContext().getPackageName());
k.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
k.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(k);
// stopForeground(true);
// unbindService(connection);
// stopSelf();
}
服务中的代码很简单。
分析
后来发现原因是因为Android10以后是不允许后台去startActivity的。如下图所示
解决方法
添加权限
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
该权限需要用户主动去开启。
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())));
}
} else {
Toast.makeText(getApplicationContext(), "API < " + android.os.Build.VERSION_CODES.M, Toast.LENGTH_SHORT).show();
}
再次重试,杀掉程序后,APP主页面马上启动起来了,完美解决。