Service前后台相关

前言:service是一种计算类型的组件,也是运行在UI线程中;service中同样也不能进行耗时操作,否则就会导致无响应,AMS就会给我弹个ANR(前台服务比后台服务的时间更短,超过就会ANR;至于多少时间就无响应,请可自行查找)。

一、首先,对service进行简单的介绍,对于service在AndroidManifest注册,只说一下process属性,不指定该属性的时候,该service依赖于app的默认进程;当为其指定属性的时候,该service便作为一个独立的进程,假设在service的process指定如下属性:

android:process="com.example.anyview.KeepLiveService"

运行项目,上图可以看到控制台有两个可选的进程,第一个是默认的进程名,第二个则是刚才指定的进程;

同时,我们在Application中的onCreate打印了一行日志,下图:

可以看到控制台的输出日志,下图:

根据输出日志可以看到,我们的日志在两个进程中分别执行一次,由此可得出onCreate也执行了两次。

根据以上结果,我们可以对于一些初始化操作进行优化,一般只需在默认进程中进行初始化即可

public boolean isMainProcess() {
    int myPid = Process.myPid();
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> appProcesses = manager.getRunningAppProcesses();
    for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
        if (myPid == appProcess.pid && appProcess.processName.equals(getPackageName())) {
            return true;
        }
    }
    return false;
}
使用上述代码判断是否主进程,这样可以加快app启动响应!这里需要注意的是在gradle更新之后,appId和包名有不同的作用,一般更多是根据包名找资源,appId作为区分不同应用。有些第三方平台也对此做了区分。如果你的项目包名跟appId不一样,那么默认进程就是appId

二、service的启动方式:

service的启动分为startService和bindService两种

1.startService(intent):首次启动service的时候,依次执行onCreate,startCommand方法!因为通过该方式启动的service不会随着应用退出而结束,必须通过调用stopService方法才能停止服务。多次startService,不会多次创建onCreate,后面会直接走startCommand方法!

2.bindService(intent,mConnection,Context.BIND_AUTO_CREATE):onBind方法!因为通过该方式启动的service在程序是和启动者绑定的,当前者退出了,该服务的unBindService方法会被调用,停止service服务!

需要注意的是,从Android 5.0之后,如果目标service和启动service的界面不在同一应用,客户端不止需要setAction("xxxx"),还需要在setPackage("目标service所在项目的包名"),如下图所示。

三、保活的两种操作:

(一)可以配合使用广播实现,这种方法适用于正常关闭的情况:

1.每当service关闭的时候,在service的onDestroy方法中发送一个广播:

Intent intent = new Intent("com.example.testBroadCastReceiver");
sendBroadcast(intent);

2.然后注册一个广播接受者,当接收到发的广播,就启动service:

public class KeepAliveBroadCastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        if ("com.example.testBroadCastReceiver".equals(intent.getAction())){
            intent = new Intent(context, KeepAliveService.class);
            context.startService(intent);
        }
    }
}

3.在manifest中进行进行注册:

<service android:name=".KeepAliveService"/>

<receiver android:name=".KeepAliveBroadCastReceiver">
    <intent-filter>
        <action android:name="com.example.testBroadCastReceiver"/>
    </intent-filter>
</receiver>

(二)启动前台service:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(new Intent(this, KeepAliveService.class));//start前台Service
}else {
    startService(new Intent(this, KeepAliveService.class));
}

Service中的startCommand如下:

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        intent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
        
        Notification.Builder builder = new Notification.Builder(this)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.app_icon))
                .setSmallIcon(R.mipmap.app_icon)
                .setContentTitle("title")
                .setContentText("例子")
                .setContentIntent(pendingIntent)
                .setWhen(System.currentTimeMillis());

        /**
         * 为了规范通知栏,在26以后必须创建通知渠道
         */
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){//sdk>=26
            NotificationChannel notificationChannel = new NotificationChannel("com.example.administrator.anyview", "AnyView", NotificationManager.IMPORTANCE_HIGH);
            mNotificationManager.createNotificationChannel(notificationChannel);
            builder.setChannelId("com.example.administrator.anyview");
        }

        startForeground(1, builder.build());//前台通知,通过stopForeground(true)关闭
//        mNotificationManager.notify(1, notification);//普通通知
        return super.onStartCommand(intent, flags, startId);
    }

所以,进程保活其实第二种才是我们最常用的方法,这样一键杀进程就杀不掉我们的应用了(只能手动单独杀)

以上是service的一些基本介绍,如有问题,欢迎指出!!

猜你喜欢

转载自blog.csdn.net/yang1164851882/article/details/78730523