Android Service组件

151 阅读4分钟

Android Service组件

基本方法和属性

Android Service组件的主要用途是在后台运行,Service 和 另一个基本组件Activity 都是从 Context 派生来的,因此都可以调用 Context中定义的一些方法。Service组件的关键方法有以下5个:

IBinder onBind(Intent intent); // 该方法必须实现,被绑定时回调。返回一个IBinder对象,应用程序与该Service的交互都通过该 IBinder对象进行
void onCreate(); //第一次创建后运行该方法
void onDestroy(); //在被关闭之前调用该方法
void onStartCommand(Intent intent, int flags, int startId); // 每次调用startService方法启动服务时都会调用该方法
void onUnbind(Intent intent); // 当该Service上绑定的所有客户端都端开连接时才运行次方法

在创建一个Service之后也需要在AndroidManifest.xml 文件中对该Service进行配置。与Activity类似,Service也可以通过设置 intent-filter来指定该Service可以被哪些Intent启动。Service配置的常见属性如下:

<service android:name=""  
         android:exported=""       
         android:permission=""  
         android:process=""
         android:enable=""
         android:foregroundServiceType=""
         android:icon=""
         android:isolatedProcess=""
         android:label=""
         >
    <intent-filter>
    	<action name=""/>
    </intent-filter>
</service>
  • name 属性:指定该Service实现类的类名;
  • exported 属性:指定该Service能否被其他应用启动,如果在配置Service时指定了 intent-filter 那么exported属性默认为 true,否则默认为 false;
  • permission 属性:指定启动该Service 需要的权限;如果startService(), bindService(), stopService() 等方法的调用者不具备该权限,那么系统不会把相应的Intent 传递给服务;如果该属性未设置,则默认使用applicaiton设置的权限,如果都没有设置那么服务不受权限保护;
  • process 属性:指定该Service所处的进程名称,默认在系统为该APP创建的进程中运行,此时该名称与应用的软件包名相同。 元素中指定的process 属性可以为自身所有组件设置不同的默认进程名称,但是组件可以使用自己的process属性来替换默认值。 如果为此属性分配的名称以冒号开头,那么服务将会在使用该名称的全局进程中运行(在其拥有权限的情况下)这样可以让不同应用中的组件共享进程,减少资源使用。使用了冒号则该进程名称为该Service完整的包名+冒号后的名称,例如,remote表示运行在名为remote的进程中,而 :remote 则表示运行在名为 包名:remote 的进程中(此时其他app无法访问该进程)。该属性 application 和 四大组件都可以设置,如果都设置了以组件自身的为准;
  • isolatedProcess 属性:如果该属性设置为 true,那么该 Service 将运行在与系统其他部分隔离开的进程中,并且该服务自身没有自己的权限,与这个Service通信只能通过服务的API进行,例如 bindService startService等;

Service 的启动和停止

  • 通过 Context 的 startService(Intent) 和 stopService(Intent) 来启动和停止 Service

    //此处假设在一个名为 MainActivity的 Activity中启动一个名为 FirstService 的服务
    Intent intent = new Intent(MainActivity.this, FirstService.class);
    startService(intent);
    stopService(intent);
    

    Android 5.0 之后 Service 组件必须使用显示 Intent 启动, 显示 Intent 必须要指定包名,可以通过Context 和目标Service类创建显示Intent,如上述代码所示,也可以通过包名和 action 属性来创建显示 Intent,如下面的代码所示:

    //此处假设FirstService所在的包名为 com.test.service, 能够响应的action为 com.test.service.action.first
    Intent intent = new Intent();
    intent.setPackage("com.test.service");
    intent.setAction("com.test.service.action.first");
    startService(intent);
    stopService(intent);
    

    Service 在被创建时会调用 onCreate 方法,但是一旦 Service 被创建了再调用 startService 则只会调用 onStartCommand 方法;

    • 使用 bindService() 和 unbindService() 来启动和停止 Service

      由于使用 startService 和 stopService 时无法与 Service实例之间建立联系,因此使用这种方式创建Service无法与之交互;通过 bindService() 和 unbindService() 时可以通过IBinder对象来实现与Service的交互;

    bindService(Intent, ServiceConnection, flags);
    

    其中,通过intent来指定要启动的 service, ServiceConnection 对象用于监听访问者与Service之间的连接情况,有onServiceConnected(ComponentName, IBinder), onServiceDisconnected(ComponentName) 方法,可以在这两个回调函数中实现一些流程控制操作;flags 用来指定如果Service还未创建时是否自动创建。

Service 的实现

在编写Service的实现类时必须提供 IBinder onBind(Intent)方法。在绑定该Service时 onBind 方法返回的 IBinder 对象会通过 onServiceConnected 方法的参数返回给调用者,实现其与Service之间的通信;