Service基础

基本介绍

Service是一个应用程序组件,四大组件之一,它能够在后台执行一些耗时较长的操作,并且不提供用户界面。服务能被其它应用程序的组件启动,即使用户切换到另外的应用时还能保持后台运行。此外,应用程序组件还能与服务绑定,并与服务进行交互,甚至能进行进程间通信(IPC)。

使用方式

Service有常见的两种启动方式,Started 和Bound 方式。

Started 方式

如果一个应用程序组件(比如一个activity)通过调用startService()来启动服务,则该服务就是被“started”了。

一旦被启动,服务就能在后台一直运行下去,即使启动它的组件已经被销毁了。

通常,started的服务执行单一的操作并且不会向调用者返回结果。比如,它可以通过网络下载或上传文件。当操作完成后,服务应该自行终止。

执行顺序: onCreate() -> onStartCommand() ->onDestroy();

销毁方式 stopService()

区别: startService()之后,无论启动的组件是否仍然存在,没有调用stopService()方法,Service仍然存在。

    /**
     * 启动服务
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:20
     */
    public void startService(View view) {
        Intent intent = new Intent(this, MyService.class);
        startService(intent);
    }

    /**
     * 关闭服务
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:20
     */
    public void stopService(View view) {
        Intent intent = new Intent(this, MyService.class);
        stopService(intent);
    }

Bound 方式

如果一个应用程序组件通过调用bindService()绑定到服务上,则该服务就是被“bound”了。

bound服务提供了一个客户端/服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至可以利用进程间通信(IPC)跨进程执行这些操作。

绑定服务的生存期和被绑定的应用程序组件一致。 多个组件可以同时与一个服务绑定,不过所有的组件解除绑定后,服务也就会被销毁。

执行顺序: onCreate() -> onBind() ->onDestroy();

销毁方式 unbindService()
注意:通过unbindService()取消Service需要判定是否bind,否则报异常

区别: bindService()即将调用绑定的组件与这个Service捆绑在一起,组件销毁了Service也被销毁,类似从属关系。

Bound方式Service与Activity通讯

1.MyService中的onBind()返回IBind子类实例。

2.ServiceConnection的onServiceConnected()方法拿出IBinder,向下强转为MyService中的IBind子类,即可对Service进行操作。

    private ServiceConnection mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("info", "onServiceConnected: ==++ 服务连接");
            MyService.MyBinder myBinder = (MyService.MyBinder) service;
            myBinder.doSomething();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("info", "onServiceDisconnected: ==++ 服务取消连接");
        }
    };

    // 标记服务是否绑定
    private boolean isBind = false;

    /**
     * 绑定服务
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:27
     */
    public void bindService(View view) {
        Intent intent = new Intent(this, MyService.class);
        bindService(intent, mServiceConn, BIND_AUTO_CREATE);
        isBind = true;
    }

    /**
     * 取消绑定服务
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:28
     */
    public void unbindService(View view) {
        if (isBind) {
            isBind = false;
            unbindService(mServiceConn);
        }
    }

MyService

/**
 * 自定义Service
 *
 * @author fengzhen
 * @version 1.0, 2017/7/21
 */
public class MyService extends Service {

    @Override
    public void onCreate() {
        Log.i("info", "onCreate: ==++ 服务创建");
        Log.i("info", "onCreate: ==++ 当前线程:" + Thread.currentThread().getName());
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("info", "onStartCommand: ==++ 服务启动");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i("info", "onDestroy: ==++ 服务销毁");
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("info", "onBind: ==++ 绑定服务");
        return new MyBinder();
    }

    public class MyBinder extends Binder {
        public void doSomething() {
            Log.i("info", "doSomething: ==+++ 做具体的事");
        }
    }
}

运行线程

通过验证可以发现,Service和Activity一样,运行在主线程,所以在使用是需要创建一个新的线程完成服务的工作
也可以使用其子类:IntentService

IntentService

创建一个缺省的工作(worker)线程,它独立于应用程序主线程来执行所有发送到onStartCommand()的intent。

创建一个工作队列,每次向你的onHandleIntent()传入一个intent,这样你就永远不必担心多线程问题了。

在处理完所有的启动请求后,终止服务,因此你就永远不需调用stopSelf()了。

提供缺省的onBind()实现代码,它返回null。

提供缺省的onStartCommand()实现代码,它把intent送入工作队列,稍后会再传给你的onHandleIntent()实现代码。

/**
 * Service服务扩展类
 *
 * @author fengzhen
 * @version v1.0, 2017/7/21
 */
public class MyIntentService extends IntentService {
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     * <p>
     * Used to name the worker thread, important only for debugging.
     */
    public MyIntentService() {
        super("MyIntentService");
    }

    /**
     * IntentService从缺省的工作线程中调用本方法,并用启动服务的intent作为参数
     * 本方法返回后,IntentService将适时终止这个服务。
     * <p>
     * 再次方法操作需要在子线程做的,使用循环的方式,直到任务完成
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 17:05
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("info", "onCreate: ==++ 当前线程:" + Thread.currentThread().getName());
        int i = 0;
        while (i < 10) {
            i++;
            // doSomething
        }
    }
}

进程间通信(IPC)

使用AIDL来进行进程间通信(IPC)

AIDL(Android Interface Definition Language):Android接口定义语言

1.更改Service在xml配置

        <service android:name=".MyService"
            android:process=":remote">
            <intent-filter>
                <action android:name="com.hftsoft.servicedemo.MyAidlInterface"/>
            </intent-filter>
        </service>

2.创建AIDL文件

这里参数类型只能使用basecTypes中的所有参数类型

AS创建AIDL文件只有需要点击 mudel 旁小锤子图标 Make Project (Ctrl + f9)

interface MyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    /**
     * 自定义简单方法
     */
    String getString(int a);
}

3.绑定Activity中实现

    private MyAidlInterface mMyAidlInterface;
    /**
     * PIC Conn
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 18:16
     */
    private ServiceConnection mServiceConnRemote = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mMyAidlInterface = MyAidlInterface.Stub.asInterface(service);
            try {
                String string = mMyAidlInterface.getString(5);
                Log.i("info", "onServiceConnected: ==++" + string);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

    // 标记服务是否绑定
    private boolean isBind = false;

    /**
     * 绑定服务 IPC
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:27
     */
    public void bindService(View view) {
        Intent intent = new Intent("com.hftsoft.servicedemo.MyAidlInterface");
        intent.setPackage(this.getPackageName());
        bindService(intent, mServiceConnRemote, BIND_AUTO_CREATE);
        isBind = true;
    }

    /**
     * 取消绑定服务 IPC
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:28
     */
    public void unbindService(View view) {
        if (isBind) {
            isBind = false;
            unbindService(mServiceConnRemote);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章