关于Service

Service 的基本用法

  要使用Service,首先新建一个类继承自Service。根据需要覆写其中的若干方法。然后在mainfest中声明这个service。其中Service标签中各个字段的含义如下

<service android:enabled=["true" | "false"]
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:isolatedProcess=["true" | "false"]
    android:label="string resource"
    android:name="string"
    android:permission="string"
    android:process="string" >
    . . .
</service>
  • android:exported:代表是否能被其他应用隐式调用,其默认值是由service中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。为false的情况下,即使有intent-filter匹配,也无法打开,即无法被其他应用隐式调用。

  • android:name:对应Service类名

  • android:permission:是权限声明

  • android:process:是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。注意“:”很重要,它的意思是指要在当前进程名称前面附加上当前的包名,所以“remote”和”:remote”不是同一个意思,前者的进程名称为:remote,而后者的进程名称为:App-packageName:remote。

  • android:isolatedProcess :设置 true 意味着,服务会在一个特殊的进程下运行,这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。

  • android:enabled:是否可以被系统实例化,默认为 true因为父标签 也有 enable 属性,所以必须两个都为默认值 true 的情况下服务才会被激活,否则不会激活。


启动服务

  启动service有两种方式,分别是调用context的startService()和bindService()方法。其中startService()方式启动的服务必须使用stopService()或者stopSelf()方法来停止服务,而通过bindService()方式启动的服务则会随着绑定对象的全部解绑而停止。


关于service的详细用法戳这里


前台服务

  前台服务指在通知栏有通知的服务,一般优先级比较高,不会轻易被系统kill掉。创建前台服务的方法很简单,在Service中调用startForeground()方法即可,参数是int类型的flag和一个notifycation。终止的方法则是stopForeground(),部分代码如下(pendingintent会单独介绍):

public class MyService extends Service {
    public MyService() {

    }

    @Override
    public void onCreate() {
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
//        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));
        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setContentTitle("通知");
        builder.setContentText("内容");
        builder.setContentIntent(pendingIntent);
        Notification notification = builder.build();
//        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        startForeground(111,notification);
    }

    @Override
    public void onDestroy() {
        stopForeground(true);
    }

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

intentService

  intentService是对service的封装,源码分析如下:

  成员变量包含了一个looper和一个handler,很容易猜出在intentService中会有子线程和线程间通信的操作,声明的代码如下:

    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

  在ServiceHandler内部类的声明中可以看出,构造方法要求传入一个Looper对象,该handler应该是要去绑定UI线程之外的Looper,handlerMessage中onHandlerIntent是一个抽象方法,由子类具体实现,也就是说在这个方法中我们去处理具体的事务。由上面的分析可知,这个方法是在子线程调用的。在onHandlerIntent之后调用了stopSelf()方法,Service被销毁。也就是说只能执行一次onHandlerIntent()方法然后服务会自动销毁。

  onCreate方法的代码如下:

@Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

  在onCreate中做了这么几件事:new了一个HandlerThread对象,启动这个thread,获取这个线程的Looper并且new了一个ServiceHandler对象,传入该Looper。果然和上面的猜测相同,handler绑定了一个子线程的looper。再来看一下HandlerThread是怎么实现的。
  HandlerThread是Thread的子类,run方法如下:

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

  主要就是对Looper进行初始化,跟普通的子线程没有太多区别。、
  回到IntentService,onCreate后面的生命周期应该是onStartCommand(),那么来看一下这个方法:

@Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

@Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

  简单来说就是把启动service的intent通过handler发到了子线程。那么IntentService的用途就明确了,就是提供了一个子线程供我们来做一些操作,并且做完这些事情后这个Service会自动销毁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值