一、MainActivity.java
@Override
protected void onPause() {
super.onPause();
// 这是前提——你的app至少运行了一个service。这里表示当进程不在前台时,马上开启一个service
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
二、MyService.java
package com.wei.wanandroid.service;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.wei.wanandroid.activity.MainActivity;
public class MyService extends Service
{
private final static String TAG = MyService.class.getSimpleName();
// 启动notification的id,两次启动应是同一个id
private final static int NOTIFICATION_ID = android.os.Process.myPid();
private AssistServiceConnection mServiceConnection;
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 测试线程,判断Service是否在工作
new Thread(mRunnable).start();
// 设置为前台进程,降低oom_adj,提高进程优先级,提高存活机率
setForeground();
return START_STICKY;
}
// 要注意的是android4.3之后Service.startForeground() 会强制弹出通知栏,解决办法是再
// 启动一个service和推送共用一个通知栏,然后stop这个service使得通知栏消失。
private void setForeground() {
if (Build.VERSION.SDK_INT < 18)
{
startForeground(NOTIFICATION_ID, getNotification());
return;
}
if (mServiceConnection == null)
{
mServiceConnection = new AssistServiceConnection();
}
// 绑定另外一条Service,目的是再启动一个通知,然后马上关闭。以达到通知栏没有相关通知
// 的效果
bindService(new Intent(this, AssistService.class), mServiceConnection,
Service.BIND_AUTO_CREATE);
}
private class AssistServiceConnection implements ServiceConnection
{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Service assistService = ((AssistService.LocalBinder)service)
.getService();
MyService.this.startForeground(NOTIFICATION_ID, getNotification());
assistService.startForeground(NOTIFICATION_ID, getNotification());
assistService.stopForeground(true);
MyService.this.unbindService(mServiceConnection);
mServiceConnection = null;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
private Notification getNotification()
{
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "")
.setContentTitle("服务运行于前台")
.setContentText("service被设为前台进程")
.setTicker("service正在后台运行...")
.setPriority(NotificationCompat.PRIORITY_MAX)
.setWhen(System.currentTimeMillis())
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setContentIntent(pendingIntent);
Notification notification = builder.build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
return notification;
}
Runnable mRunnable = new Runnable() {
@Override
public void run() {
while (true)
{
Log.e(TAG, "" + System.currentTimeMillis());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
@Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
}
三、AssistService.java
package com.wei.wanandroid.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class AssistService extends Service {
public AssistService() {
}
public class LocalBinder extends Binder
{
public AssistService getService()
{
return AssistService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return new LocalBinder();
}
}
四、测试结果
app退回桌面后(还没调用startForeground):
shell@libra:/ $ cat proc/29346/oom_adj
7
app退回桌面后(调用startForeground):
shell@libra:/ $ cat proc/6338/oom_adj
2
结论:很明显通过startForeground,oom_adj从7降到2。能把进程优先级提高到接近前台进程的高度。能有效地保活app。
网友评论