.服务生命周期,开启方式,绑定服务,远程服务

android应用程序的四大组件

  • activity 界面

  • content provider 内容提供者 暴露应用程序私有的数据

  • broadcast receiver 接受广播消息

  • service 后台的服务

四大组件都要在清单文件配置,特殊广播接受者(代码,清单文件)

Service

一个组件长期后台运行,没有界面。 简单的理解:service理解成一个没有界面长期运行的activity。

配置一个服务

第一步 创建一个类,然后继承Service类,在创建的类中写服务的功能

第二步 因为是服务,所以要在配置文件中进行声明

    <service android:name="c.c.c.c.MyService"></service>

第三步 开启服务

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

服务的生命周期 (重要)

开启服务

onCreate() -->onStartCommand-->onStart(过时) -->ondestory(销毁) 如果服务已经开启了,就不会重新调用oncreate方法,服务只会被创建一次

//开启服务
public void start(View view){
    Intent intent = new Intent(this,MyService.class);
    startService(intent);
}
//停止服务
public void stop(View view){
    Intent intent = new Intent(this,MyService.class);
    stopService(intent);
}
停止服务业可以直接通过ddms,选中进程然后关掉

服务有两种开启方法

  • startService(); 直接开启服务,服务一旦启动跟调用者(开启者没有任何关系)

调用者activity退出了,服务还是继续运行活的好好的。 调用者activity,没法访问服务里面的方法。

  • bindService(); 绑定开启服务,服务和开启者(调用者)有密切的关系。

** 不求同时生,但求同时死。只要activity挂了,服务跟着挂了。** 调用者activity,可以调用服务里面的方法。

绑定方式开启服务,调用服务方法的流程 (重要)

绑定服务的生命周期 oncreate()-->onbind()--->onDestory(); 不会调用onstart()方法 和 onstartCommand()方法。

绑定的过程

在activity中

第一步 使用bindService的方式开启服务。

    bindService(intent, new MyConn(), Context.BIND_AUTO_CREATE);

第二步 实现一个MyConn 服务与activity的通讯频道(中间人的联系渠道)

    private class MyConn implements ServiceConnection{
        /**
         * 当服务被成功绑定的时候执行的方法,得到中间人。
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binder = (MyBinder) service;
        }
        /**
         * 当服务失去绑定的时候调用的方法。当服务突然异常终止的时候
         */
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

在MyService中

第三步 服务成功绑定的时候 会执行onBinde方法,返回中间人

     public class MyBinder extends Binder{
         /**
          * 内部人员帮助我们调用服务的方法。
          */
         public void callMethodInService(){
             methodInService();
         }
    }

第四步 在activity代码里面通过中间人调用服务的方法。

public void impl(View view){
    mybinder.callMethodInService();

}

第五步 解绑服务

public void jiebang(View view){
    unbindService(conn);
}

抽取接口,隐藏私有方法。

将要让中间人能够执行的方法写进一个接口中,并且让中间人实现只能执行的方法的接口,然后调用者在创建中间人的时候,调用接口中的方法

见代码

调用者activity

public class MainActivity extends Activity {
    IService binder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    /**
     * 绑定服务
     * @param view
     */
    public void bind(View view){
        Intent intent = new Intent(this,MyService.class);
        //1.开启服务的时候 必须使用 绑定的方式开启。
        System.out.println("1. 第一步,开启服务 bind方式。");
        bindService(intent, new MyConn(), Context.BIND_AUTO_CREATE);
    }

    private class MyConn implements ServiceConnection{
        /**
         * 当服务被成功绑定的时候执行的方法
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //3.通讯频道得到服务成功绑定的消息,得到中间人
            System.out.println("3. 第三步,成功绑定服务后,在通讯频道里面得到中间人"+service.toString());
            binder = (IService) service;
        }
        /**
         * 当服务失去绑定的时候调用的方法。当服务突然异常终止的时候
         */
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }


    /**
     * 调用服务的方法
     * @param view
     */
    public void call(View view){
        System.out.println("4.调用中间人的方法。");
        binder.callMethodInService(3000);
    }
}

对外提供服务的方法

public interface IService {
    public void callMethodInService(int money);
}

服务本身的方法(服务本身有些敏感的方法不能让外部调用)

public class MyService extends Service {

    /**
     * 官员的小蜜 。潜规则
     * 
     * @author Administrator
     * 
     */
    //重点地方!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    private class MyBinder extends Binder implements IService{
        /**
         * 内部人员帮助我们调用服务的方法。
         * 
         * @param money
         *            如果大于2000 执行,小于两千 ,给个提示
         */
        public void callMethodInService(int money) {
            if (money >= 2000) {
                System.out.println("5.中间人,调用服务的方法");
                methodInService();
            }else{
                Toast.makeText(MyService.this, "再准备点,你懂的", 0).show();
            }
        }

        public void playMajiang(){
            System.out.println("一起打麻将");
        }

        public void xisangna(){
            System.out.println("一起洗桑拿");
        }
    }

    /**
     * 官员内部的方法,为人民币服务,没有2000块钱是不会执行的。
     */
    public void methodInService() {
        Toast.makeText(this, "我是服务内部的方法,我被调用了。", 0).show();
    }

    @Override
    public IBinder onBind(Intent intent) {
        MyBinder mybinder = new MyBinder();
        System.out.println("2. 第二步 服务被成功绑定了。---onbind,返回IBinder代理人"
                + mybinder.toString());
        return mybinder;// 返回中间人
    }

    @Override
    public void onCreate() {
        System.out.println("服务被创建了---oncreate()");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        System.out.println("服务被销毁了");
        super.onDestroy();
    }
}

远程服务

aidl: android interface definition language(安卓接口定义语言)

Local-side IPC implementation

本地内部进程通信的实现。

什么是远程服务:服务的代码在另外一个应用程序里面。 什么是本地服务:服务的代码在当前应用程序里面。

以上面的代码为例

服务端需要做的配置

1.远程服务修改接口文件的扩展名为aidl,删除访问修饰符public

IService.java 改为 IService.aidl

interface IService {
    void callMethodInService(int money);
}

2.修改IBinder的实现类 extends IService.Stub

private class MyBinder extends IService.Stub{
    /**
     * 内部人员帮助我们调用服务的方法。
     * 
     * @param money
     *            如果大于2000 执行,小于两千 ,给个提示
     */
    public void callMethodInService(int money) {
        if (money >= 2000) {
            System.out.println("5.中间人,调用服务的方法");
            methodInService();
        }else{
            Toast.makeText(MyService.this, "再准备点,你懂的", 0).show();
        }
    }

3,对外提供IService.aidl

4.对外提供服务

    <service android:name="com.itheima.remoteservice.MyService">
        <intent-filter >
            <action android:name="com.itheima.remote.service"/>
        </intent-filter>
    </service>

客户端配置

第一步.访问远程服务的时候必须使用绑定的方式开启(通过意图开启)

public void bind(View view){
    //1.开启服务的时候 必须使用 绑定的方式开启。
    System.out.println("1. 第一步,开启服务 bind方式。");
    Intent intent = new Intent();
    intent.setAction("com.itheima.remote.service");
    bindService(intent, new MyConn(), Context.BIND_AUTO_CREATE);
}

第二步.在调用者的工程里面,把远程服务的aidl文件拷贝过来,保证包名也完全一致。

第三步.在调用者里面强制类型转化

iService = com.itheima.remoteservice.IService.Stub.asInterface(service);

private class MyConn implements ServiceConnection{
    /**
     * 当服务被成功绑定的时候执行的方法
     */
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //3.通讯频道得到服务成功绑定的消息,得到中间人
        System.out.println("3. 第三步,成功绑定服务后,在通讯频道里面得到中间人"+service.toString());
        iService = com.itheima.remoteservice.IService.Stub.asInterface(service);
    }
    /**
     * 当服务失去绑定的时候调用的方法。当服务突然异常终止的时候
     */
    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
}

第四步.调用远程服务的方法

public void call(View view){
    try {
        iService.callMethodInService(5000);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}
原文地址:https://www.cnblogs.com/fengchuxiaodai/p/5324098.html