1.Service为什么会被杀死?
1>手机内存不足时,Service有可能被杀死;
2>360,手机管家等优化内存时,Service可能被杀死;
2.进程的优先级
1.前台进程
用户当前操作所必需的进程。如果一个进程满足以下任一条件,即视为前台进程:
- 托管用户正在交互的Activity已调用Activity的onResume()方法
- 托管某个Service,后者绑定到用户正在交互的 Activity
- 托管正在“前台”运行的Service服务已调用startForeground()
- 托管正执行一个生命周期回调的Service (onCreate() 、onStart()或onDestroy())
- 托管正执行其onReceive()方法的BroadcastReceiver
通常,在任意给定时间前台进程都为数不多。只有在内存不足以支持它们同时继续运行这一万不得已的情况下,系统才会终止它们。 此时,设备往往已达到内存分页状态,因此需要终止一些前台进程来确保用户界面正常响应。
2.可见进程
没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。 如果一个进程满足以下任一条件,即视为可见进程:
- 托管不在前台、但仍对用户可见的Activity已调用其onPause()方法。例如,如果前台 Activity 启动了一个对话框,允许在其后显示上一 Activity,则有可能会发生这种情况。
- 托管绑定到可见(或前台)Activity 的Service。
可见进程被视为是极其重要的进程,除非为了维持所有前台进程同时运行而必须终止,否则系统不会终止这些进程。
3.服务进程
正在运行已使用startService()方法启动的服务且不属于上述两个更高类别进程的进程。尽管服务进程与用户所见内容没有直接关联,但是它们通常在执行一些用户关心的操作(例如,在后台播放音乐或从网络下载数据)。因此,除非内存不足以维持所有前台进程和可见进程同时运行,否则系统会让服务进程保持运行状态。
4.后台进程
包含目前对用户不可见的 Activity 的进程已调用 Activity 的onStop()方法。这些进程对用户体验没有直接影响,系统可能随时终止它们,以回收内存供前台进程、可见进程或服务进程使用。 通常会有很多后台进程在运行,因此它们会保存在 LRU (最近最少使用)列表中,以确保包含用户最近查看的 Activity 的进程最后一个被终止。如果某个 Activity 正确实现了生命周期方法,并保存了其当前状态,则终止其进程不会对用户体验产生明显影响,因为当用户导航回该 Activity 时,Activity 会恢复其所有可见状态。 有关保存和恢复状态的信息,请参阅Activity文档。
5.空进程
不含任何活动应用组件的进程。保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间。 为使总体系统资源在进程缓存和底层内核缓存之间保持平衡,系统往往会终止这些进程。
3.保活ServiceDemo:
MsgService:
public class MsgService extends Service {
@Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
Log.e("tag","hello world!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(0,new Notification());
bindService(new Intent(this,GiGiService.class),
serviceConnection, Context.BIND_IMPORTANT);
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ProcessCon.Stub() {
};
}
public ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
startService(new Intent(MsgService.this,GiGiService.class));
bindService(new Intent(MsgService.this,GiGiService.class),
serviceConnection, Context.BIND_IMPORTANT);
}
};
}
GiGiService:
public class GiGiService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(1,new Notification());
bindService(new Intent(this,MsgService.class),
serviceConnection, Context.BIND_IMPORTANT);
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ProcessCon.Stub() {
};
}
public ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
startService(new Intent(GiGiService.this,MsgService.class));
bindService(new Intent(GiGiService.this,MsgService.class),
serviceConnection, Context.BIND_IMPORTANT);
}
};
}
以上就是所谓的双进程守护,在4.4机型上测试,设置里面找到运行的服务,确实能达到效果,但是360,腾讯管家等还是可以杀死进程!
引入JobWakeUpService:
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class JobWakeUpService extends JobService {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
JobInfo.Builder builder = new JobInfo.Builder(1,
new ComponentName(this,JobWakeUpService.class));
builder.setPeriodic(500);
JobInfo jobInfo = builder.build();
JobScheduler jobScheduler = (JobScheduler)
getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);
return START_STICKY;
}
@Override
public boolean onStartJob(JobParameters params) {
boolean isMessageAlive = isServiceWork(this,MsgService.class.getName());
if(!isMessageAlive){
// startService(new Intent(this,GuardService.class));
startService(new Intent(this,MsgService.class));
}
return false;
}
/**
* 判断某个服务是否正在运行的方法
*
* @param mContext
* @param serviceName
* 是包名+服务的类名(例如:net.loonggg.testbackstage.TestService)
* @return true代表正在运行,false代表服务没有正在运行
*/
public boolean isServiceWork(Context mContext, String serviceName) {
boolean isWork = false;
ActivityManager myAM = (ActivityManager) mContext
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> myList =
myAM.getRunningServices(100);
if (myList.size() <= 0) {
return false;
}
for (int i = 0; i < myList.size(); i++) {
String mName = myList.get(i).service.getClassName().toString();
if (mName.equals(serviceName)) {
isWork = true;
break;
}
}
return isWork;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
配置清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.michael.ipc3">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED">
</uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MsgService">
</service>
<service android:name=".GiGiService">
</service>
<service android:name=".JobWakeUpService"
android:enabled="true"
android:permission="android.permission.BIND_JOB_SERVICE"
>
</service>
</application>
初识启动服务:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this,MsgService.class));
startService(new Intent(this,GiGiService.class));
startService(new Intent(this,JobWakeUpService.class));
}
}