- Process Priority
-
Improving process priority
- Method 1 starts a 1-pixel activity
- Method 2 Dual Process Guardian can prevent a single process from killing while preventing a third party's 360 from cleaning up one process from being killed and another process from being started by him to monitor each other and start killing process. The essence of killing process is to race with killing process time. Here cross-process communication uses AIDL.
In android development, service is usually used to handle background tasks. When the system process space is tight, the process recovery will be carried out automatically according to the priority.
Process Priority
1. Front-end process: Foreground process.
- Activeness (onResume ()) in which users are interacting
- When a Service binds Activeness that is interacting
- Initially called as a front-end Service (startForeground())
- The component is executing callbacks for its lifecycle (onCreate()/onStart()/onDestroy())
- Broadcast Receiver is executing onReceive()
2. Visible process: Visible process
- Activity is in onPause() (no onStop())
- Service bound to front-end Activity
3. Service process: Service process
- Simple startService() startup
4. Background process
- Processes that have no direct impact on users - when Activity comes out of onStop()
- android:process=":xxx"
5. Empty process
- Components that do not contain any activity. (android designed a trade-off for faster second startup)
Improving process priority
Method 1: Start a 1-pixel activity
1. Create a transparent activity of 1-pixel activity
Window window = getWindow();
window.setGravity(Gravity.LEFT|Gravity.TOP);
LayoutParams params = window.getAttributes();
params.height = 1;
params.width = 1;
params.x = 0;
params.y = 0;
window.setAttributes(params);
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowDisablePreview">true</item>
<item name="android:windowNoDisplay">false</item>
2. Create broadcasts that listen for opening, unlocking and locking screens, and call back
private class ScreenBroadcastReceiver extends BroadcastReceiver {
private String action = null;
@Override
public void onReceive(Context context, Intent intent) {
action = intent.getAction();
if (Intent.ACTION_SCREEN_ON.equals(action)) { // Open screen
mScreenStateListener.onScreenOn();
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // Lock screen
mScreenStateListener.onScreenOff();
} else if (Intent.ACTION_USER_PRESENT.equals(action)) { // Unlock
mScreenStateListener.onUserPresent();
}
}
}
private void registerListener() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
mContext.registerReceiver(mScreenReceiver, filter);
}
public interface ScreenStateListener {// Returns screen status information to caller
public void onScreenOn();
public void onScreenOff();
public void onUserPresent();
}
3. Create a Service to perform listening tasks
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
ScreenListener listener = new ScreenListener(this);
listener.begin(new ScreenStateListener() {
@Override
public void onUserPresent() {
}
@Override
public void onScreenOn() {
// Open Screen - finish this one-pixel Activity
}
@Override
public void onScreenOff() {
// Lock Screen - Start Activeness of a Pixel
}
});
}
Method 2: Dual-process guardianship can prevent a single process from killing, and at the same time prevent a third party from cleaning up 360. One process is killed, and the other is started by him, listening to each other. Killing process is a killing process, the essence of which is a race against killing process time. AIDL is used for cross-process communication.
1. Create a local process, write interfaces and methods
<service
android:name="xxxx"
android:process=":remoteprocess">
</service>
2. Create a Service to communicate with the local process, and then create a Service to listen to each other. The two services code logic is the same.
private MyBinder binder;
private MyServiceConnection conn;
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onCreate() {
super.onCreate();
if(binder ==null){
binder = new MyBinder();
}
conn = new MyServiceConnection();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LocalService.this.bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);
PendingIntent contentIntent = PendingIntent.getService(this, 0, intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setTicker("360")
.setContentIntent(contentIntent)
.setContentTitle("I am 360. Who am I afraid of?!")
.setAutoCancel(true)
.setContentText("hehehe")
.setWhen( System.currentTimeMillis());
//Set the service to run in the front desk to avoid the mobile phone system automatically killing and changing the service.
startForeground(startId, builder.build());
return START_STICKY;
}
class MyBinder extends RemoteConnection.Stub{
@Override
public String getProcessName() throws RemoteException {
return "LocalService";
}
}
class MyServiceConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "Connect successfully!");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "RemoteService The service was destroyed.~~~~Disconnect!");
Toast.makeText(LocalService.this, "Disconnect", 0).show();
//The startup was destroyed
LocalService.this.startService(new Intent(LocalService.this, RemoteService.class));
LocalService.this.bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);
}
}
3. Finally, another terrible thing is to use Job Scheduler every few seconds to judge whether the service is running or not, and start the service without it, so that it can hardly kill.
private int kJobId = 0;
@Override
public void onCreate() {
super.onCreate();
Log.i("INFO", "jobService create");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("INFO", "jobService start");
scheduleJob(getJobInfo());
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
@Override
public boolean onStartJob(JobParameters params) {
// TODO Auto-generated method stub
Log.i("INFO", "job start");
// scheduleJob(getJobInfo());
boolean isLocalServiceWork = isServiceWork(this, "com.dn.keepliveprocess.LocalService");
boolean isRemoteServiceWork = isServiceWork(this, "com.dn.keepliveprocess.RemoteService");
// Log.i("INFO", "localSericeWork:"+isLocalServiceWork);
// Log.i("INFO", "remoteSericeWork:"+isRemoteServiceWork);
if(!isLocalServiceWork||
!isRemoteServiceWork){
this.startService(new Intent(this,LocalService.class));
this.startService(new Intent(this,RemoteService.class));
Toast.makeText(this, "process start", Toast.LENGTH_SHORT).show();
}
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
Log.i("INFO", "job stop");
// Toast.makeText(this, "process stop", Toast.LENGTH_SHORT).show();
scheduleJob(getJobInfo());
return true;
}
/** Send job to the JobScheduler. */
public void scheduleJob(JobInfo t) {
Log.i("INFO", "Scheduling job");
JobScheduler tm =
(JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
tm.schedule(t);
}
public JobInfo getJobInfo(){
JobInfo.Builder builder = new JobInfo.Builder(kJobId++, new ComponentName(this, JobHandleService.class));
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
builder.setPersisted(true);
builder.setRequiresCharging(false);
builder.setRequiresDeviceIdle(false);
builder.setPeriodic(10);//Interval time - period
return builder.build();
}
/**
* A method to determine whether a service is running
*
* @param mContext
* @param serviceName
* Is the class name of the package + service (e.g. net.loonggg.testbackstage.TestService)
* @return true The representative is running, and the false representative service is not running
*/
public boolean isServiceWork(Context mContext, String serviceName) {
boolean isWork = false;
ActivityManager myAM = (ActivityManager) mContext
.getSystemService(Context.ACTIVITY_SERVICE);
List<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;
}