Service调优相关

Service是一个后台服务,专门用来处理常驻后台工作的组件。

即时通讯:service来做常驻后台的心跳传输。

核心服务尽可能轻,很多人喜欢把所有的后台操作放在一个service里面,这是不太好的,因为“树大招风”。应该核心服务专门做一个进程,跟其他所有后台操作隔离。

进程的重要性优先级(从高到低):
1. 前台进程:
  • 用户正在交互的Activity;
  • 当某个Service绑定正在交互的Activity;
  • 被主动调用为前台的Service(startForegroud());
  • 组件正在执行声明周期的回调
  • 广播接收者(BroadcastReceiver)正在执行onResume
2. 可见进程
  • Activity处于onPause()(没有进入onStop())
  • 绑定到前台Activity的Service
3.服务进程

简单的startService()启动

4. 后台进程

对用户没有直接影响的进程,比如Activity处于onStop()的时候

5. 空进程

不含有任何活动的组件。安卓设计的,为了第二次启动更快,采取的权衡。。当我们退出一个app后,其实这个进程还是存在的,这是系统这么设计的。

如何提升进程的优先级

提高进程优先级,尽量做到不轻易被系统杀死。

1.QQ采取在锁屏的时候启动一个1像素的Activity(注意:锁屏界面在上面),当用户解锁(或者是开屏)以后,要将这个Activity结束,顺便把自己的核心服务再开启。

背景:当手机锁屏的时候什么都干死了,为了省电。

下面我们就简单实现一个例子。

//屏幕广播接收以及状态回调的类
public class ScreenListener {
    private Context mContext;
    private ScreenBroadcastReceiver mScreenReceiver;
    private ScreenStateListener mScreenStateListener;

    public ScreenListener(Context context) {
        mContext = context;
        mScreenReceiver = new ScreenBroadcastReceiver();
    }

    /**
     *广播接收
     */
    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)) { //开屏
                mScreenStateListener.onScreenOn();
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏
                mScreenStateListener.onScreenOff();
            } else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁
                mScreenStateListener.onUserPresent();
            }
        }
    }

    /**
     * 初始化
     * 
     * @param listener
     */
    public void begin(ScreenStateListener listener) {
        mScreenStateListener = listener;
        registerListener();
        getScreenState();
    }

    /**
     *获取屏幕状态
     */
    private void getScreenState() {
        PowerManager manager = (PowerManager) mContext
                .getSystemService(Context.POWER_SERVICE);
        if (manager.isScreenOn()) {
            if (mScreenStateListener != null) {
                mScreenStateListener.onScreenOn();
            }
        } else {
            if (mScreenStateListener != null) {
                mScreenStateListener.onScreenOff();
            }
        }
    }


    public void unregisterListener() {
        mContext.unregisterReceiver(mScreenReceiver);
    }

    /**
     * 注册广播接收
     */
    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 {
        public void onScreenOn();

        public void onScreenOff();

        public void onUserPresent();
    }
}
//控制1像素的activity显示和消失的Service
public class KeepService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        ScreenListener listener=new ScreenListener(this);
        listener.begin(new ScreenListener.ScreenStateListener() {
            @Override
            public void onScreenOn() {
                //开屏
                KeepLiveActivityManager.getInstance(KeepService.this).finishKeepLiveActivity();
            }

            @Override
            public void onScreenOff() {
                //锁屏
                KeepLiveActivityManager.getInstance(KeepService.this).startKeepLiveActivity();
            }

            @Override
            public void onUserPresent() {
                //解锁后
            }
        });
    }

    /**
     * 补充:
     * 锁屏-->回调onScreenOff
     * 按键后屏幕亮--->onScreenOn
     * 不解锁,再锁屏-->onScreenOff
     * 按键后屏幕亮--->onScreenOn
     * 解锁-->onUserPresent
     */
}
//1个像素的activity
public class KeepLiveActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Window window = getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.width=1;
        params.height=1;
        params.x=0;
        params.y=0;
        window.setGravity(Gravity.LEFT|Gravity.TOP);
        window.setAttributes(params);

        KeepLiveActivityManager.getInstance(this).setKeepLiveActivity(this);
        System.out.println("-----KeepLiveActivity:onCreate-----");

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.out.println("-----KeepLiveActivity:onDestroy-----");
    }
}
//activity的管理类
public class KeepLiveActivityManager {
    private static KeepLiveActivityManager instance;
    private Context context;
    private WeakReference<Activity> activityInstance;

    public static KeepLiveActivityManager getInstance(Context context) {
        if(instance==null){
            instance = new KeepLiveActivityManager(context.getApplicationContext());
        }
        return instance;
    }

    private KeepLiveActivityManager(Context context) {
        this.context = context;
    }

    public void setKeepLiveActivity(Activity activity){
        activityInstance = new WeakReference<Activity>(activity);
    }

    public void startKeepLiveActivity() {
        Intent intent = new  Intent(context, KeepLiveActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
    public void finishKeepLiveActivity() {
        if(activityInstance!=null&&activityInstance.get()!=null){
            Activity activity = activityInstance.get();
            activity.finish();
        }
    }

}

    <style name="KeepLiveStyle">
        <!--背景透明-->
        <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>
    </style>
//清单文件注册activity
<activity android:name=".KeepLiveActivity"
            android:theme="@style/KeepLiveStyle"/>
<service android:name=".keep.KeepService"/>

当然了千万不要忘了启动Service

 Intent intent=new Intent(MainActivity.this, KeepService.class);
2.app运营商和手机厂商合作,加入白名单。
3.双进程守护

一个进程被杀死,另一个进程又把它启动,相互监听启动。本质是和杀进程时间赛跑。
利用双进程守护可以保证在停止单个服务(应用管理->正在运行)后又启动服务或者第三方清理软件清理失败。
下面是两个不同进程的Service,相互监听,不同进程间通信用到了AIDL。

public class LocalService extends Service {
    public static final String TAG = "gxh";
    private MyBind binder;
    private MyServiceConnection conn;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if (binder == null) {
            binder = new MyBind();
        }

        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);

//        Notification notification=new Notification(R.mipmap.ic_launcher,"哈哈哈哈",System.currentTimeMillis());
//        notification.contentIntent= PendingIntent.getService(this,0,intent,0);

        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setTicker("hahaha")
                .setSmallIcon(R.mipmap.ic_launcher)//设置小图标
                .setContentTitle("LocalService")
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)//点击后消失
                .setContentText("ContentText")
                .setWhen(System.currentTimeMillis());
        Notification notification=builder.build();

        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.notify(0, notification);//显示通知
        //设置为前台,尽量避免被系统杀死
        startForeground(startId, notification);
        return START_STICKY;
    }

    class MyBind extends face.gxh.cn.imeitext.aidl.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, "local--onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "local--onServiceDisconnected");
            Global.showToast("RemoteService断开了");
            //RemoteService断开了,所以要重新启动这个服务
            LocalService.this.startService(new Intent(LocalService.this,RemoteService.class));
            LocalService.this.bindService(new Intent(LocalService.this,RemoteService.class),
                    conn, Context.BIND_IMPORTANT);

        }
    }
}
public class RemoteService extends Service {

    public static final String TAG="gxh";
    private MyBind binder;
    private MyServiceConnection conn;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if(binder==null){
            binder=new MyBind();
        }

        conn=new MyServiceConnection();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //绑定
        RemoteService.this.bindService(new Intent(RemoteService.this, LocalService.class),
                conn, Context.BIND_IMPORTANT);

//        Notification notification=new Notification(R.mipmap.ic_launcher,"哈哈哈哈",System.currentTimeMillis());
//        notification.contentIntent= PendingIntent.getService(this,0,intent,0);

        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setTicker("hahaha")
                .setContentTitle("RemoteService")
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .setContentText("ContentText")
                .setWhen(System.currentTimeMillis());
        Notification notification=builder.build();

        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.notify(1, notification);//显示通知


        //设置为前台,尽量避免被系统杀死
        startForeground(startId, notification);
        return START_STICKY;
    }

    class MyBind extends face.gxh.cn.imeitext.aidl.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,"remote--onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG,"remote--onServiceDisconnected");
            Global.showToast("LocalService断开了");
            //LocalService断开了
            RemoteService.this.startService(new Intent(RemoteService.this,LocalService.class));
            RemoteService.this.bindService(new Intent(RemoteService.this,LocalService.class),
                    conn, Context.BIND_IMPORTANT);

        }
    }
}

AIDL的创建:
创建aidl文件夹,右键new->AIDL->AIDL FILE->修改文件名->Finish->在生成的aidl文件中写你的方法->重新编译一下。
注意生成的对应的java文件在app->build->generated->source->aidl

// RemoteConnection.aidl
package face.gxh.cn.imeitext.aidl;

// Declare any non-default types here with import statements

interface RemoteConnection {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
//    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
//            double aDouble, String aString);

    String getProcessName();
}

注册:

<service android:name=".doubl.LocalService"/>
<service android:name=".doubl.RemoteService"
        android:process=":remoteprogress"/>

启动:

startService(new Intent(MainActivity.this, LocalService.class));
startService(new Intent(MainActivity.this, RemoteService.class));
4.JobScheduler

详见下一篇文章吧。

5.监听QQ、微信、系统应用等的广播,然后启动自己
6.利用账号同步唤醒我们的进程
7.NDK解决,native进程来实现双进程守护。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值