天天看点

Android学习笔记 Service(part.2)Day14 Service

Day14 Service

  • IntentService
  • BindService
  • AIDL实现跨进程服务
  • MediaPlayer
  • Timer

IntentService

IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。

另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

  • 关键方法
  • 注意事项

关键方法

除其他Service生命周期方法外:

* ==

onHandleIntent(Intent)

==

在该方法中进行耗时操作,由IntentService中封装的异步任务完成

处理异步请求的IntentService,其内有一个工作线程来处理耗时操作

内部使用了单线程池模式(所以每次只执行一个任务,完成后再进行第二个)

注意事项

创建IntentService子类时,需要提供一个==无参==的构造方法且调用:

==

super(null)

==

BindService

基于IBinder方式将两个组件进行绑定,然后相互传值.

如果以绑定的方式启动的服务,在解除绑定时也会自动停止服务.

需创建自定义Binder子类并通过onBind()返回

  • 生命周期方法
  • 使用步骤
  • 绑定类型

生命周期

除其他Service生命周期方法外:

  • ==

    IBinder onBind(Intent)

    ==
    • 返回自定义的Binder的子类
    • 返回Messenger的getBinder()
  • ==

    onUnBind(Intent)

    ==
    • 解除绑定时回调
  • ==

    onReBind(Intent)

    ==
    • 重新绑定时回调

使用步骤

bindService的过程:

* 在Service组件中,声明Binder类的子类(公共),在其子类中声明组件之间的接口方法

* 在onBind()方法中,实例化Binder子类的对象,并返回

* 在绑定服务组件端(Activity),实例化ServiceConnection接口对象

* 在ServiceConnection接口对象的onServiceConnected()方法中,将方法的第二个参数IBinder对象强转成Binder子类对象

* 在适当的位置 调用 Context.bindService()来绑定服务。

创建类,继承Service,并现实onBind()方法
在Service组件中,声明Binder类的子类(公共),在其子类中声明组件之间的接口方法
public class MyService extends Service{
        public IBinder onBind(Intent intent) {
            ...
        }

        public class MyBinder extends Binder{
            public void MyMethod1(){
                ...
            }
            public void MyMethod2(){
                ...
            }
            ...
        }
    }
           
在onBind()方法中,实例化Binder子类的对象,并返回
@Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();//实例化Binder的子类,并返回
    }
           

在绑定服务组件端(Activity),实例化ServiceConnection接口对象

在ServiceConnection接口对象的onServiceConnected()方法中,将方法的第二个参数IBinder对象强转成Binder子类对象

ServiceConnection conn=new ServiceConnection(){
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 绑定成功的方法
            myBinder=(MyBinder) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // 与绑定服务组件断开连接(发生的时机:由于系统原因造成了服务组件停止或销毁)
            myBinder=null;
        }
    };
           
在适当的位置 调用 Context.bindService()来绑定服务。
//绑定服务组件
    bindService(new Intent(getApplicationContext(),TimerService.class),
                conn, BIND_AUTO_CREATE);

    //BIND_AUTO_CREATE标识表示:绑定的服务组件如果不存,则会自动创建,
    //注:由bindService方式启动的Service,其生命周期会受到绑定组件的影响,即当绑定组件Activity销毁时,Service也会停止
           
解除绑定
//解除绑定
    Context.unBindService(Intent)
           

绑定类型

绑定服务的类型:

* ==

BIND_AUTO_CREATE

==

- 绑定的service不存在时,会自动创建

* ==

BIND_ADJUST_WITH_ACTIVITY

==

- service的优先级别与根据所绑定的Activity的重要程度有关,Activity处于前台,service的级别高

* ==

BIND_NOT_FOREGROUND

==

- Service永远不拥有运行前台的优先级

* ==

BIND_WAIVE_PRIORITY

==

- Service的优先级不会改变

* ==

BIND_IMPORTANT | BIND_ABOVE_CLIENT

==

- 所绑定的Activity处于前台时,Service也处于前台

- BIND_ABOVE_CLIENT 指定内存很低的情况下,运行时在终止绑定的Service之前终止Activity

AIDL实现跨进程服务

一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码

个人理解:

为了能使两个进程(应用)之间通信,二者需要持有同一个通讯工具,即通过AIDL文件定义的接口

当一个应用使用AIDL文件时,会自动生成其定义的java接口,通过这个接口实现与目标服务的通信接驳

  • AIDL支持的数据类型
  • 使用方法案例

AIDL支持的数据类型

AIDL默认支持的类型:

  • java基本类型:==

    int

    ==、==

    long

    ==、==

    boolean

    ==、==

    float

    ==、==

    double

    ==、==

    char

    ==
  • 引用类型及集合:==

    String[]

    ==、==

    List

    ==、==

    Map

    ==

使用方法案例

使用步骤概览

服务端:

- 服务端创建.aidl文件和声明接口

- 创建类,继承Service,并实现onBind方法

- 在Service类中定义aidl中声明接口的Stub对象,并实现aidl接口中声明的方法

- 在onBind方法中返回Stub对象

- 在AndroidManifest.xml中注册Service并声明其Action

客户端:

- Context.bindService(new Intent(接口的类名,ServiceConnection,int)

- 定义ServiceConnection对象

onServiceConnected(ComponentName,IBinder)
    onServiceDisconnected()
    //aidl接口对象=AIDLService.Stub.asInterface(server)
           
  • 在Activity定义aidl接口对象

样例

IRemoteService.AIDL

package com.qf.aidl;

    interface IRemoteService{

    void print(String msg);

    String getName();
}
           
  • RemoteService.java
public class RemoteSerice extends Service {
    //2.1 实例化.aidl接口的Stub对象
    private IRemoteService.Stub stub=new IRemoteService.Stub() {
        @Override
        public void print(String msg) throws RemoteException {
            Log.i("debug", "--RemoteSerice---"+msg);
        }
        @Override
        public String getName() throws RemoteException {
            return "RemoteSerice";
        }
    };
    @Override
    public IBinder onBind(Intent intent) {
        return stub;//2.2 返回aidl接口的Stub对象
    }
}
           
  • (Client)
//声明aild接口对象
    IRemoteService remoteService;

    //实例化绑定组件之间的通信接口
    ServiceConnection conn=new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //将第二个参数转化为.aidl接口对象
            remoteService=IRemoteService.Stub.asInterface(service);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //绑定其它应用的Service组件,在绑定成功之后,将返回的Stub对象转化为aidl接口对象
        bindService(new Intent("com.qf.serivce04_aidl_server.RemoteSerice"),
                conn, BIND_AUTO_CREATE);

    }
           

MediaPlayer

用于播放音乐和视频文件

构造方法:==

MediaPlayer()

==

通过静态方法(create)构造会直接进入prepared状态

通过静态方法构造:==

MediaPlayer create(Context context, int resid)

==

常用方法

  • ==

    setDataSource(String path)

    == 设置媒体源
  • ==

    setLooping(boolean)

    == 设置是否循环播放
  • ==

    prepare()

    == 预处理,调用start()前必须先调用此方法
  • ==

    start()

    == 开始播放
  • ==

    pause()

    ==暂停播放
  • ==

    stop()

    == 停止播放
  • ==

    isPlaying()

    == 是否正在播放
  • ==

    reset()

    == 重置播放器,进入idle空闲状态
  • ==

    release()

    == 释放资源
  • ==

    getDuration()

    == 获取播放文件的总时长,单位:毫秒
  • ==

    getCurrentPosition()

    == 获取当前播放的位置
  • ==

    seekTo(int position)

    == 定位到指定的播放时间

Timer定时器

按排一段定时任务在指定的时间执行,对于提醒相关的任务,应该设置重复间隔时间

关键方法

  • ==

    schedule(TimerTask task, Date when)

    == 按排任务在指定时间执行
  • ==

    schedule(TimerTask task, long delay)

    == 按排任务延迟多少毫秒之后执行
  • ==

    schedule(TimerTask task, long delay, long period)

    == 按排任务在延迟多个毫秒后执行,并间隔多少毫秒后重复
  • ==

    cancel()

    == 取消定时器

TimerTask 定时任务

TimerTask 定时任务类,是实现Runnable接口的抽象类

样例

timer.schedule(new TimerTask(){
        @Override
        public void run() {
            // TODO 在指定的时间执行的任务

            NotificationCompat.Builder builder=
                    new NotificationCompat.Builder(getApplicationContext());
            builder.setSmallIcon(android.R.drawable.ic_menu_today)
                    .setContentTitle("提醒")
                    .setContentText("时间了,该起床了....")
                    .setTicker("时间了,该起床了....")
                    .setDefaults(Notification.DEFAULT_SOUND)
                    .setOngoing(true);

            notifyMgr.notify(, builder.build());
        }
    },*, *);