Android Service要点

作者:陆金龙    发表时间:2018-03-24 22:11   


1. 什么是Service以及描述下它的生命周期;Service有哪些启动方法,有什么区别;怎样停用Service?

 startService

生命周期onCreate()--->onStartCommand()--->onStart()--->onDestroy()

可以多次调用,不会重复创建,oncreate()只执行一次,会多次调用onStart

以start方式开启的服务也只能停止一次,多次调用stopservice()是无效的,只会调用一次onDestroyed。

以start方式开启的服务,调用者退出,服务仍然可以正常运行

不能调用服务中的方法

外部调用stopService可以停止服务,停止的时候调用onDestroy方法。

bindService

生命周期onCreate() --->onBind() -->onUnbind()---->onDestry()。

可以调用服务中的方法。

与绑定的Activity一同销毁,调用者在onDestroy()的时,系统会调用服务的onUnbind()
-->onDestroy()。

Activity调用bindService绑定服务(同一个Activity只能成功绑定一次,之后的绑定无效,onBind不再重复执行,onServiceConnected也不会再次回调)。

MainActivy中通过bindService绑定了KLService ,按返回退出MainActivy,执行流程如下:

03-24 21:14:30.558 22847-22847/com.klfront.platform.debug I/kl: KLService -> onCreate

03-24 21:14:30.559 22847-22847/com.klfront.platform.debug I/kl: KLService -> onBind, from:MainActivity

03-24 21:14:30.644 22847-22847/com.klfront.platform.debug I/kl: MainActivity ->onServiceConnected num=-1995123560

03-24 21:14:41.431 22847-22847/com.klfront.platform.debug I/kl: MainActivity -> onDestroy

03-24 21:14:41.457 22847-22847/com.klfront.platform.debug I/kl: KLService -> onUnbind, from:MainActivity

03-24 21:14:41.459 22847-22847/com.klfront.platform.debug I/kl: KLService -> onDestroy, Thread: main

 

绑定的Activity调用unbindService解绑,Srevice就会调用onUnbind- >onDestroyed,然后Service销毁(同一个绑定者不可多次调用,会报异常)。

MainActivy中通过bindService绑定了KLService ,先调用unbindService,再按返回退出MainActivy,执行流程如下:

03-24 21:17:32.344 25798-25798/com.klfront.platform.debug I/kl: KLService -> onCreate

03-24 21:17:32.344 25798-25798/com.klfront.platform.debug I/kl: KLService -> onBind, from:MainActivity

03-24 21:17:32.492 25798-25798/com.klfront.platform.debug I/kl: MainActivity ->onServiceConnected num=1022166858

03-24 21:17:36.349 25798-25798/com.klfront.platform.debug I/kl: KLService -> onUnbind, from:MainActivity

03-24 21:17:36.349 25798-25798/com.klfront.platform.debug I/kl: KLService -> onDestroy, Thread: main

03-24 21:17:42.123 25798-25798/com.klfront.platform.debug I/kl: MainActivity -> onDestroy

 

多个Activity绑定一个Service,unbindServie流程:

已经被bindService方式启动后,新的Activity 再bindService时,没有调用onBind(),但服务会回调onServiceConnected ,将IBind对象传递回来

 

当前Activity与Service解除绑定时,Service先检测是否还与其他Activity连接

如果没有,Service执行onUnbind方法,然后在执行onDestroy方法,正常销毁。

如果有,Service不会执行onUnbind和onDestroy方法,Service继续运行。

start MainActvity->bindService->start DialogActivty->bindService->unbindService->DialogActivty 退出->回到MainActvity->调用unbindService,日记如下(DialogActivty中unbindService没有Service并没有销毁):

03-24 21:01:25.045 16945-16945/com.klfront.platform.debug I/kl: KLService -> onCreate

03-24 21:01:25.045 16945-16945/com.klfront.platform.debug I/kl: KLService -> onBind, from:MainActivity

03-24 21:01:25.188 16945-16945/com.klfront.platform.debug I/kl: MainActivity ->onServiceConnected num=1459452050

03-24 21:01:42.358 16945-16945/com.klfront.platform.debug I/kl: DialogActivity -> onServiceConnected num=-1292470555

03-24 21:01:58.694 16945-16945/com.klfront.platform.debug I/kl: DialogActivity -> onDestroy, Thread: main

03-24 21:02:15.391 16945-16945/com.klfront.platform.debug I/kl: KLService -> onUnbind, from:MainActivity

03-24 21:02:15.391 16945-16945/com.klfront.platform.debug I/kl: KLService -> onDestroy, Thread: main

2.混合方式使用Service

按以下顺序使用

startService(保证服务的长期后台运行)

bindService(保证调用服务的方法)

unbindService(解除绑定,保证调用stopService时能正常停止服务)

stopService

 

如果bindService,使用完后没有unbindService,会导致stopService

执行失败。

 

Service只被创建一次,onCreate只被调用一次,无论多少次的startService又bindService,第二次都会跳过onCreate,直接走后面的生命周期。

3. service是否在main thread中执行,service里面是否能执行耗时的操作?

      默认Service和activity是运行在当前app所在进程的main thread(UI主线程)。

service里面不能执行耗时的操作(网络请求,拷贝数据库,大文件)。

      可以在清单文件配置android:process,service 执行所在的进程 ,让service在另外的进程中执行。如:<service android:name="MyService" android:process=":my_process" />

4. 怎么在activity中启动自己对应的service?Activity怎么和service绑定?

     startService() 一旦被创建,与调用者无关,没法使用service里面的方法

       bindService () 把service 与调用者绑定,让activity能够访问到 service里面的方法。

如果调用者都被销毁, service会销毁。

       Intent service = new Intent(this,MyService.class);

bindService(intent,new MyConn(), BIND_AUTO_CREATE);//BIND_AUTO_CREATE

       private class MyConn implements ServiceConnection {

// 重写onServiceConnected和OnServiceDisconnected方法

                   publicvoid onServiceConnected(ComponentName name, IBinder service) {

                   // 可以通过IBinder的对象 去使用service里面的方法

                    }

                    publicvoid onServiceDisconnected(ComponentName name) {

                    }

}

5.不同应用Activity绑定另一个App的Service的情况

前提:App B的Service已经启动。

第一次:App A绑定Service,创建了IntentBindRecord实例,记录在AppBindRecord中。 
执行onBind()后,App B进程通过publishService()将binder传给了AMS,记录在IntentBindRecord实例中,并设置标志位received。

第二次:App C绑定Service时,获取之前的IntentBindRecord实例。

判断标志位received为true,直接调用App C的onServiceConnected()将binder对象传给App C。 
所以第二次没有调用onBind()。

6. 说说Activity,Intent,Service是什么关系

      职责上各自负责不同的功能。

      activity和service通过intent去激活组件,传递数据.

      笔记网络更新功能,显示界面用的activity, 后台有个service每隔10分钟访问下服务器同步数据(上传和下载),用的是intent来开启服务。

7. 什么是IntentService?有何优点?

  普通的service ,默认运行在ui main 主线程。

  IntentService是Sdk给我们提供的方便的,带有异步处理的service类,

  OnHandleIntent()处理耗时的操作。

8. 什么时候使用Service?

     startForeground(id, notification)

   拥有service的进程具有较高的优先级

    Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。

   1. 如果service正在调用onCreate,  onStartCommand或者onDestory方法,那么用于当前service的进程相当于前台进程以避免被killed。

   2. 如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.

   3. 如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。

   4. 如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。

   如果有其他的应用组件作为Service,与Activity等运行在相同的进程中,那么将会增加该进程的重要性。

   1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作.

   2.Broadcastreceiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作.

   3.远程的service如果被启动起来,可以被多次bind,但不会重新create.索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用.

 

9. 不用service,B页面为音乐播放,从A跳转到B,再返回,如何使音乐继续播放?

       默认不做任何处理,B里面的音乐都能播放。

   A开启B的时候,用startActivityForResult()方法, B返回的时候把播放的状态信息返回给A ,A继续播放音乐。

 

3进程间通信示例:

代码来源:Android中bindService的细节之二:从进程的角度分析绑定Service的流程【Service所在进程已存在】

IAnyService.aidl

package com.galian.app_b;

interface IAnyService {

    String getData();

}

App B的代码

AnyService.java(IAnyService接口的具体实现)

public class AnyService extends IAnyService.Stub {

    @Override

    public String getData() throws RemoteException {

        return "Any String";

    }

}

 

MyService.java

public class MyService extends Service {

    AnyService service = null;

    @Override

    public void onCreate() {

        super.onCreate();

        service = new AnyService();

    }

    @Override

    public IBinder onBind(Intent intent) {

        return service;

    }

}

 

App A的代码

点击button,绑定service

    Intent intent = new Intent();

    intent.setClassName("com.galian.app_b", "com.galian.app_b.MyService");

    bindService(intent, mSvcConn, Context.BIND_AUTO_CREATE);

ServiceConnection:

    private IAnyService mAnyService = null;

    private ServiceConnection mSvcConn = new ServiceConnection() {

        @Override

        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

            mAnyService = IAnyService.Stub.asInterface(iBinder);

            if (mAnyService != null) {

                try {

                    String data = mAnyService.getData();

                }

            }

        }

    };