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


    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();
        }
    }
  • 相关阅读:
    Win7下使用TortoiseGit设置保存密码
    MacOS软件清单
    ubuntu安装python
    Mac使用SSH连接远程服务器
    CentOS常用命令
    Docker追加容器端口映射
    Docker安装CentOS7
    Windows操作路由表
    Docker部署MySQL8并实现远程连接
    Qt——容器类(译)
  • 原文地址:https://www.cnblogs.com/fengchuxiaodai/p/5324098.html
Copyright © 2020-2023  润新知