美文网首页
Chapter 08. Service&AIDL

Chapter 08. Service&AIDL

作者: GeekGray | 来源:发表于2018-10-12 21:00 被阅读5次

阅读原文

8.1 理论概述

Service是一个应用组件, 它用来在后台完成一个时间跨度比较大的工作
且没有关联任何界面

一个Service可以完成下面这些工作:
访问网络

播放音乐

文件IO操作

大数据量的数据库操作

……
服务的特点:
• Service在后台运行,不用与用户进行交互

• 即使程序被切换到后台,或者用户打开新的应用,服务仍可运行

• 服务并非运行在独立的进程中,而是依赖于创建服务的应用程序进
程。如果某个应用进程被杀掉,该服务也会停止

• 在默认情况下, Service运行在应用程序进程的主线程(UI线程)中,
如果需要在Service中处理一些网络连接等耗时的操作,那么应该将
这些任务放在Service的分线程中处理,避免阻塞用户界面

8.1.2 区别Service与Activity

Activity:

  • Activity对应一个界面

  • 应用退出, Activity对象就会死亡

  • 应用再次进入, 启动的Activity对象是重新创建的

Service

  • 不与任何界面关联,绝不会到前台来

  • 应用退出, Service仍在运行

  • 应用再次进入, 启动的Service还是前面运行的Service对象


8.1.3 Activity 与 Service 的选择标准:

  • 如果某个应用程序组件需要运行时向用户呈现某种界面,或者该程序
    需要与用户交互,就需要使用Activity,否则就应该考虑使用Service。

8.1.4 区别Service与Thread

Service

  • 用来在后台完成一个时间跨度比较大的工作的应用组件

  • Service的生命周期方法运行在主线程, 如果Service想做持续时间比
    较长的工作, 需要启动一个分线程(Thread)

  • 应用退出: Service不会停止

  • 应用再次进入: 可以与正在运行的Service进行通信

Thread

  • 用来开启一个分线程的类, 做一个长时间的工作

  • Thread对象的run()在分线程执行

  • 应用退出: Thread不会停止

  • 应用再次进入: 不能再控制前面启动的Thread对象


8.1.5 Service的分类

1. Local Service(****本地服务)

Service对象与Service的启动者在同个进程中运行, 两者的通信是进程

内通信

2. Remote Service(****远程服务)

Service对象与Service的启动者不在同一个进程中运行, 这时存在一个

进程间通信的问题, Android专门为此设计了AIDL来实现进程间通信


8.1.6 使用本地Service

image image

8.1.6 AIDL

每个应用程序都运行在自己的独立进程中,并且可以启动另一个应用
进程的服务,而且经常需要在不同的进程间传递数据对象。
在Android平台,一个进程不能直接访问另一个进程的内存空间,所
以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且
有序的通过进程边界。

AIDL (Android Interface Definition Language) 用于生成可以在Android设备上两个进程之间进行进程间通信
(interprocess communication, IPC)的代码。

如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)
对象的操作,就可以使用AIDL生成可序列化的参数。

image

8.2 服务的创建

创建一个MyService类继承自Service,此时会自动实现onBind()方法,MyService中的代码如下所示:

public class MyService extends Service
{
    public IBinder onBind(Intent intent)
    {
        return null;
    }
}

onBind()方法是Service类中唯一的抽象方法,所以必须要在子类中实现。

在功能清单文件中注册MyService,否则服务是不生效的

<service android:name="cn.itcast.servicetest.MyService"/>

8.3 服务的生命周期

与其他组件不同的是,Service不能自己主动运行,需要调用相应的方法来启动。启动服务方法有两个,分别是Context。startService()和Context.bindService()。使用不同的方法启动服务,服务的生命周期也会不同。

image

8.3.1 startService()方式开启服务的生命周期

当其他组件调用startService()方法时,服务会先执行onCreate()方法,接着执行onStartCommand()方法,此时服务处于运行状态,直到自身调用stopSelf()方法或者其他组件调用stopService()方法时服务停止,最终被系统销毁。这种方式开启的服务会长期的在后台运行,并且服务的状态与开启者的状态没有关系。需要注意的是,onCreate()方法只有在服务创建时执行,而onStartCommand()方法则是每次启动服务时调用。

8.3.2 bindService方式开启服务的生命周期

当其他组件调用bindService()方法时,服务被创建,接着客户端通过Ibinder接口与服务通信。客户端通过unbindService()方法关闭连接,多个客户端能绑定到同一个服务上,并且当它们都解绑时,系统直接消耗服务。这种方式开启的服务与开启者的状态有关,当调用者销毁了,服务也会被销毁。

8.3.3 生命周期方法作用

  • onCreate():第一次创建服务时执行的方法

  • onDestory():服务被销毁时执行的方法

  • onStartCommand():客户端通过调用startService(Intent service)显示启动服务时执行该方法。

  • onBind():客户端通过调用bindService(Intent,Service,int)启动服务时执行该方法。

  • onUnbind():客户端调用unBindService(ServiceConnection conn)断开服务绑定时执行的方法。


8.4 服务的启动方式

startService()和bindService()方法启动服务

8.4.1 start方式启动服务

Context的startService()和stopService()方法来启动、关闭服务,代码示例如下:

Intent intent=new Intent(this,StartService.class);

Context.startService(intetnt);//开启服务

Context.stopService(intent);//关闭服务

Intent对象时用于指定要启动或者关闭服务的。当然,还需要在清单文件中注册服务MyService,如下:

<service android:name="cn.itcast.bindservice.MySerivce"/>

8.4.2 bind方式启动服务

当程序使用startService()和stopService()启动、关闭服务时,服务于调用者之间基本不存在太多的关联,也无法与访问者进行通信、数据交互等。如果服务需要与调用者进行方法调用和数据交互时,应该使用bindService()和unbindService()启动、关闭服务。

bindService()方法的完整方法名为bindService(Intent service,ServiceConnection conn,int flags),该方三个参数解释如下:

  • Intent对象用于指定要启动的Service

  • ServiceConnection对象用于监听者调用者与Service之间的连接状态。当调用者与Service连接成功时将回调该对象的onServiceConnected(ComponentName name,IBinder service)方法。断开连接时将回调该对象的onServiceDisconnected(ComponentName name)方法。

  • flags指定绑定时是否自动创建Service(如果Service还未创建)。该参数可指定为0,即不自动创建,也可以指定为BIND_AUTO_CREATE即自动创建。


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

//创建MyConn类,用于实现连接服务
private class MyConn implements ServiceConnection
{
    //当成功绑定服务时调用的方法,返回MyService里面的Ibinder对象
    public void onServiceConnected(ComponentName name,IBinder service)
    {
        //MyBinder是服务中继承Binder的内部类
        MyBinder myBinder=(MyBinder)service;
    }

    //当服务失去连接时调用的方法
    public void onServiceDisconnected(ComponentName name)
    {

    }
}

Myconn myconn=new MyConn();

//参数1是Intent,参数2是连接对象,参数3是flag表示如果服务不存在就直接创建
Context.bindService(intetn,myconn,BIND_AUTO_CREATE);

Context.unbindService(myconn);//解绑服务

需要注意的是ServiceConnection中的onServiceConnected()方法有一个参数IBinder service,这个参数是在服务中的onBind()方法中返回的。

创建服务类

public class Myservice extends Service
{
    //创建服务的代理,调用服务中的方法
    class MyBinder extends Binder
    {
        public void callMethodInService()
        {
            methodInservice();
        }
    }

    public void methodInService()
    {
        Log.i("MyService","自定义方法methodInService()");
    }

    //其他回调方法和自定义方法
    ......
}

编写界面交互代码

public class MainActivity extends Activity
{
    private MyBinder myBinder;
    private MyConn myconn;
    
    protected void onCreate(){}

    //绑定服务
    public void btn_bind(View view)
    {
        if(myconn==null)
        {
            myconn=new MyConn();
        }

        Intent intent=new Intent(this,MyService.class);
        bindService(intent,myconn,BIND_AUTO_CREATE);
    }

    //解绑服务
    public void btn_unbind(View view)
    {
        if(myconn!=null)
        {
            unbindService(myconn);
            myconn=null;
        }
    }

    //调用服务中的方法
    public void  btn_call(View view)
    {
        myBinder.callMethodInService();
    }

    //创建MyConn类,用于实现连接服务
    private class MyConn implements ServiceConnection
    {
        //当成功绑定到服务时调用的方法,返回MyService里面的Ibinder对象
        public void onServiceConnected(ComponentName name,IBinder service)
        {
            myBinder=(MyBinder)service;
            Log.i("MainActivity","服务绑定成功,内存地址为:"+myBinder.toString());
        }
        
        //当服务失去连接时调用的方法
        public void onServiceDisConnected(ComponentName name)
        {

        }
    }
}

8.5 服务通信

在Android中,服务的通信有2种:一是本地服务通信,一种是远程服务通信。本地服务通信是指应用程序内部的通信,而远程通信是指两个应用程序之间的通信。使用这两者方式进行通信时必须满足一个前提,就是服务必须以绑定方式开启。

8.5.1 本地服务通信

首先需要开发一个Service类,该类提供一个IBinder onBind(Intent intent)方法,onBind()方法返回的IBinder对象会作为参数传递给ServiceConnection类中的onServiceConnected(ComponentName name,IBinder service)方法,这样访问者就可以通过IBinder对象与Service进行通信

服务在进行通信时实际上使用的就是IBinder对象,在ServiceConnection类中得到的IBinder对象,通过该对象可以获取到服务中定义的方法,执行具体操作。

8.5.2 远程服务通信

在Android中,各个应用程序都运行在自己的进程中,进程之间一般无法直接进行通信,如果想要完成不同进程之间的通信,就需要使用远程服务通信。远程服务通信通过AIDL(Android Interface Definition Language)实现,它是一种接口定义语言(Interface Definition Language),其语法非常简单,与Java中定义的接口很相似,但是存在几点差异,具体如下:

  • AIDL定义接口的源代码必须以.aidl 结尾
  • AIDL接口中用到的数据类型,除了基本数据类型、String、List、Map、CharSEquence之外,其他类型全部都需要导入包,即使他们在同一个包中。
  • 开发人员定义的AIDL接口只是定义了进程之间的通信接口,服务端、客户端都需要使用Android SDK安装目录下的platform-tools子目录下的aidl.exe工具为该接口提供实现。如果开发者使用ADT工具进行开发,那么ADT工具会自动实现AIDL接口。

定义AIDL接口的示例代码

package cn.itcast.service;

interface IService
{
    String getName();

    int getPrice();
}

需要注意的是,AIDL没有类型修饰符,在编写AIDL文件时,不能加上类型修饰符

定义好AIDL接口之后,接着需要在应用程序中创建Service的子类。该Service的onBind()方法所返回的IBinder对象应该是ADT所生成的IService.Stub的子类。如下:

public class MyService extends Service
{
    //继承IService.stub
    private class IServiceBinder extends Stub
    {
        public String getName()throw RemoteException
        {
            return "HASH";
        }

        public int getPrice()throws RmoteException
        {
            return 100;
        }
    }

    public IBinder onBind(Intent intetn)
    {
        //第一步执行onBind方法
        return new IServiceBind();
    }
    
    public void onCreate()
    {
        super.onCreate();
    }
}

SeekBar的使用

SeekBar允许用户拖动滑块改变SeekBar的值,例如手机音量调节,同时SeekBar还允许用户改变滑块的外观,

  • andriod:thumb:指定一个Drawable对象,该对象将作为自定义滑块。
  • 监听器OnSeekBarChangeListener:监听滑块位置的改变
  • 方法setProgress():用来设置SeekBar的当前值
  • 方法SetMax():设置SeekBar的最大值。

MediaPlayer的使用

常用方法名称 功能描述
setAudioStreamType() 指定音频文件的类型必须在prepare()方法之前调用
setDataSource() 设置要播放的音频文件的位置
prepare() 在开始播放之前调用这个方法完成准备工作
start() 开始或继续播放音频
pause() 暂停播放音频
reset() 将MediaPlayer对象重置到刚刚创建的状态
seekTo() 从指定的位置开始播放音频
release() 释放掉与MediaPlayer对象相关的资源
isPlaying() 判断当前MediaPlayer是否正在播放音频
getDuration() 获取载入音频文件的时长
getCurrentPosition() 获取当前播放音频文件的位置

相关文章

网友评论

      本文标题:Chapter 08. Service&AIDL

      本文链接:https://www.haomeiwen.com/subject/zqfnaftx.html