美文网首页
Android Service

Android Service

作者: 二旬一月 | 来源:发表于2020-06-07 23:33 被阅读0次

    生命周期

    service生命周期.png

    默认情况下同进程使用

    1. 通过StartService启动Service
      startService() --> onCreate --> onStartCommand() --> stopService --> onDestroy()
    • 多次startService不会重复执行onCreate回调,但每次都会执行onStartCommand回调
    1. 通过bindService启动Service
      bindService() --> onCreate() --> onBind() --> unbindService() --> onUnbind() --> onDestroy()
    • bindService启动的服务和调用者之间是典型的client-server模式
    • 当没有任何client与Service绑定时,Service会自行销毁

    注意事项

    • service 不是运行在子线程当中的,如果有耗时操作需要开启子线程,否则会引起ANR。
    • service 是四大组件之一,使用之前必须在清单文件中进行注册。
     <service android:name=".myservice"
                android:enabled="true"
                android:exported="true"
                android:icon="@drawable/background_blue"
                android:label="string"
                android:process="string"
                android:permission="string">
     </service>
    

    android:exported 表示是否允许除了当前程序之外的其他程序访问这个服务
    android:enabled 表示是否启用这个服务
    android:permission 是权限声明
    android:process 是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。
    android:isolatedProcess 设置 true 意味着,服务会在一个特殊的进程下运行,这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。

    • onDestroy() 当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等,这是服务接收的最后一个调用。

    代码示例

    startService 模式

    public class StartService extends Service {
    
        private static final String TAG = "StartService";
        private boolean running = false;
    
        public StartService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.e(TAG,"==StartService is start with onCreate==");
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.e(TAG,"==StartService is onStart with onStartCommand==");
            running = true;
            new Thread(){
                @Override
                public void run() {
                    super.run();
                    while (running){
                        Log.e(TAG,"StartService is running");
                        try {
                            sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            return super.onStartCommand(intent, flags, startId);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.e(TAG,"==StartService is stop with onDestroy==");
            running = false;
        }
    }
    

    启动和停止服务

    findViewById(R.id.buttonstart).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //启动服务
                    startService(new Intent(MainActivity.this,StartService.class));
                }
            });
    
    findViewById(R.id.buttonstop).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //关闭服务
                    stopService(new Intent(MainActivity.this,StartService.class));
                }
            });
    

    bindService模式

    public class BindService extends Service {
    
        private static  final String TAG = "BindService";
        private long beginTime;
    
        //2.初始化Binder对象
        private MyBinder binder = new MyBinder();
    
        //1.创建Binder类,并且提供返回该服务的方法,client 可以通过Binder获取Service实例
        public class MyBinder extends Binder{
            public BindService getService(){
                return BindService.this;
            }
        }
        //3.将binder返回给client
        @Override
        public IBinder onBind(Intent intent) {
            Log.e(TAG,"BindService is onBind");
            return binder;
        }
    
        @Override
        public boolean onUnbind(Intent intent) {
            Log.e(TAG,"BindService is onUnbind");
            return super.onUnbind(intent);
        }
    
        public BindService() {
        }
    
    
        @Override
        public void onCreate() {
            super.onCreate();
            beginTime = System.currentTimeMillis();
            Log.e(TAG,"BindService is onCreate");
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.e(TAG,"BindService is onDestroy");
    //        beginTime = 0;
        }
    
        public long getRunningTime() throws Exception {
            if (beginTime == 0){
                throw new Exception("BindService is not bind!!");
            }
            return System.currentTimeMillis() - beginTime;
        }
    
    }
    
    

    绑定和解绑

        private BindService bindService;
        //1. 创建ServiceConnection,用于接收service返回的Binder对象
        private ServiceConnection connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.e("MainActivity","onServiceConnected");
                //得到Binder对象,并且通过getService()方法获取到service
                BindService.MyBinder myBinder = (BindService.MyBinder)service;
                bindService = myBinder.getService();
            }
            //Android 系统会在与服务的连接意外中断时调用该方法,当客户端取消绑定时不会调用该方法
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.e("MainActivity","onServiceDisconnected");
            }
        };
    
     findViewById(R.id.buttonbind).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(MainActivity.this,BindService.class);
                    intent.putExtra("name","MainActivity");
                    //绑定服务
                    bindService(intent,connection,BIND_AUTO_CREATE);
                }
            });
    
    findViewById(R.id.buttonunbind).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //解除绑定
                    unbindService(connection);
                }
            });
    //完成绑定后,便可以在client中使用服务中的方法了。
    long getServiceRunningTime() throws Exception {
            return bindService.getRunningTime();
        }
    

    跨进程使用

    简单的使用方式Message

    1. 服务实现一个 Handler,由其接收来自客户端的每个调用的回调
    2. Handler 用于创建 Messenger 对象(对 Handler 的引用)
    3. Messenger 创建一个 IBinder,服务通过 onBind() 使其返回客户端
    4. 客户端使用 IBinder 将 Messenger(引用服务的 Handler)实例化,然后使用Messenger将 Message 对象发送给服务
    5. 服务在其 Handler 中(在 handleMessage() 方法中)接收每个 Message

    代码示例

    这里 MessengerService 服务是运行在另一个进程的。
    <service
                android:name=".MessengerService"
                android:enabled="true"
                android:exported="true"
                android:process=":another"/>
    
    public class MessengerService extends Service {
    
        private static final String TAG ="MessengerService";
    
        public MessengerService() {
        }
    
        // 定义一个内部类集成Hanlder 用于接收client 发送过来的数据
        class MyHanlder extends Handler{
            @Override
            public void handleMessage(@NonNull Message msg) {
                switch (msg.what){
                    case 1:
                        Log.e(TAG,"message is "+msg.what);
                        break;
    
                    case 2:
    
                        break;
    
                    default:
                        super.handleMessage(msg);
                }
            }
        }
    
        // 创建 Messenger ,传入Hanlder 实例对象
        final Messenger mMessenger = new Messenger(new MyHanlder());
    
        @Override
        public IBinder onBind(Intent intent) {
            Log.e(TAG,"MessengerService is bind");
            return mMessenger.getBinder();
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.e(TAG,"MessengerService is Create");
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.e(TAG,"MessengerService is Destroy");
        }
    }
    
    

    绑定和通讯代码

    private boolean isBind = false;
        private Messenger mMessenger;
        private ServiceConnection connection_messenger = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //通过服务端传递的IBinder对象,创建相应的Messenger,
                //并且通过这个IBinder 进行通讯
                mMessenger = new Messenger(service);
                Log.e("MainActivity","connection_messenger --》 onServiceDisconnected");
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };
    findViewById(R.id.messenger).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    bindService(new Intent(MainActivity.this, MessengerService.class), connection_messenger,
                            BIND_AUTO_CREATE);
                    isBind = true;
                }
            });
    
            findViewById(R.id.sendmsg).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!isBind) return;
                    // 创建与服务交互的消息实体Message
                    Message msg = Message.obtain(null, 1, 0, 0);
                    try {
                        //发送消息
                        mMessenger.send(msg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
    
            findViewById(R.id.messenger_unbind).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (isBind){
                        unbindService(connection_messenger);
                        isBind = false;
                    }
                }
            });
    

    注意事项
    在Messenger中进行数据传递必须将数据封装到Message中,Message可以传递的信息载体有,what,arg1,arg2,Bundle以及replyTo,至于object字段,对于同一进程中的数据传递确实很实用,但对于进程间的通信,则显得相当尴尬,在android2.2前,object不支持跨进程传输,但即便是android2.2之后也只能传递android系统提供的实现了Parcelable接口的对象,也就是说我们通过自定义实现Parcelable接口的对象无法通过object字段来传递,因此object字段的实用性在跨进程中也变得相当低了。不过所幸我们还有Bundle对象,Bundle可以支持大量的数据类型。

    有时候我们可能还需要服务端能回应客户端,这时便需要提供双向消息传递了
    示例

        //用于接收服务器返回的信息
        private Messenger mRecevierReplyMsg= new Messenger(new ReceiverReplyMsgHandler());
        private static class ReceiverReplyMsgHandler extends Handler {
    
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    //接收服务端回复
                    case 2:
                        Log.e("MainActivity", "MessengerService 返回数据:"+msg.getData().getString("msg"));
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        }
    
    

    发送数据时的修改

    findViewById(R.id.sendmsg).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!isBind) return;
                    //单向
                    // 创建与服务交互的消息实体Message
    //                Message msg = Message.obtain(null, 1, 0, 0);
    //                try {
    //                    //发送消息
    //                    mMessenger.send(msg);
    //                } catch (RemoteException e) {
    //                    e.printStackTrace();
    //                }
    
                    //双向
                    // 创建与服务交互的消息实体Message
                    Message msg = Message.obtain(null, 2, 0, 0);
                    //把接收服务器端的回复的Messenger通过Message的replyTo参数传递给服务端
                    msg.replyTo=mRecevierReplyMsg;
                    try {
                        //发送消息
                        mMessenger.send(msg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
    

    MessengerService 做一下修改

    // 定义一个内部类集成Hanlder 用于接收client 发送过来的数据
        class MyHanlder extends Handler{
            @Override
            public void handleMessage(@NonNull Message msg) {
                switch (msg.what){
                    case 1:
                        Log.e(TAG,"message is "+msg.what);
                        break;
    
                    case 2:
                        Log.e(TAG,"message is "+msg.what);
                        //回复客户端信息,该对象由客户端传递过来
                        Messenger client=msg.replyTo;
                        //获取回复信息的消息实体
                        Message replyMsg=Message.obtain(null,2);
                        Bundle bundle=new Bundle();
                        bundle.putString("msg","返回数据");
                        replyMsg.setData(bundle);
                        //向客户端发送消息
                        try {
                            client.send(replyMsg);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        break;
    
                    default:
                        super.handleMessage(msg);
                }
            }
        }
    

    通过Messenger 实现服务之间通讯的图解


    MessengerService.png

    相关文章

      网友评论

          本文标题:Android Service

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