博客
关于我
Android bind service讲解以及跨进程通信
阅读量:233 次
发布时间:2019-02-28

本文共 8532 字,大约阅读时间需要 28 分钟。

**

Android bind service讲解以及Messenger跨进程通信

**

android service是运行在后台的程序,说白了,就是没有界面,这里我想强调的一点是,运行在后台不等于运行在非主线程,除了IntentService外,普通的service如果你没有开启新的线程,那么默认是运行在主线程中的。
service有两种启动方式,一个是bind,一个是start,两种启动方式,有挺多区别。需要注意的是,bind绑定service的时候,直到最后一个bind到service的程序调用unbind,否则service一直会运行。而对于startservice这种启动方式来说,一旦启动,需要自己stopService或者调用service内部的stopSelf,否则该service是不会关闭的。
还需要注意的是service的声明周期,这个附张图就全明白了。
这里写图片描述
需要注意的是,onCreate方法只在你启动service的时候调用一次,之后再启动service的时候就直接走到onStartCommand()或者onBind()里了。

好了,废话不多说了,上个demo吧:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{       private boolean hasBound;    private Button intent_Service;    private Button start_Service;    private Button bind_Service;    private Button messenger_Service;    //下面的handler和Messenger使用来进行跨进程通信的    private Handler handler=new Handler()    {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if(msg.what==322)            {                Toast.makeText(getApplicationContext(),"receive message from server",Toast.LENGTH_SHORT).show();            }        }    };    private Messenger clientMessenger=new Messenger(handler);    private Messenger serverMessenger;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();    }    private void initView()    {        intent_Service= (Button) findViewById(R.id.intent_service);        intent_Service.setOnClickListener(this);        start_Service= (Button) findViewById(R.id.start_service);        start_Service.setOnClickListener(this);        bind_Service=(Button)findViewById(R.id.bind_service);        bind_Service.setOnClickListener(this);        messenger_Service=(Button)findViewById(R.id.messenger_service);        messenger_Service.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch(v.getId())        {            case R.id.intent_service:            //启动IntentService                Intent intentService=new Intent(this,IntentTestService.class);                startService(intentService);                break;            case R.id.start_service:            //start调用普通Sservice                Intent startService=new Intent(this,NormalService.class);                startService(startService);                break;            case R.id.bind_service:            //bind调用service                Intent bindService=new Intent(this,NormalService.class);                if(bindService.resolveActivity(getPackageManager())!=null)                bindService(bindService,connection,BIND_AUTO_CREATE);                break;//利用Messenger进行跨进程通信            case R.id.messenger_service:                if(!hasBound) {                    Intent intent = new Intent("com.skateboard.serverservice.service.BIND");                    intent.setPackage("com.skateboard.serverservice");                    bindService(intent, messengerConnection, Context.BIND_AUTO_CREATE);                }                else                {                    sendMessageToServier();                }                break;        }    }    private ServiceConnection messengerConnection=new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            hasBound=true;            serverMessenger=new Messenger(service);            Message message=new Message();            message.what=233;            message.replyTo=clientMessenger;            try {                serverMessenger.send(message);            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName name) {          hasBound=false;        }    };    private ServiceConnection connection=new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            NormalService.NormalBinder binder= (NormalService.NormalBinder) service;            binder.bindMethod();        }        @Override        public void onServiceDisconnected(ComponentName name) {        }    };    private void sendMessageToServier()    {        Message message=new Message();        message.what=233;        message.replyTo=clientMessenger;        try {            serverMessenger.send(message);        } catch (RemoteException e) {            e.printStackTrace();        }    }    @Override    protected void onDestroy() {        super.onDestroy();    }}

IntentTestService继承子IntentService,它的功能很简单,就是打印一行话 “intent service start”。比较特别的就是就如如上所说的,这个service是运行在非主线程的。

public class IntentTestService extends IntentService {       public IntentTestService()    {       super("IntentTestService");    }    /**     * Creates an IntentService.  Invoked by your subclass's constructor.     *     * @param name Used to name the worker thread, important only for debugging.     */    public IntentTestService(String name) {        super(name);    }    @Override    protected void onHandleIntent(Intent intent) {        System.out.println("intent service start");    }}

NormalService可以接受startService()的方式启动同时也可以接受bindService的方式启动,这里主要讲讲bindService的启动方式,当我们bind到一个service的时候,回调用的onBind方法,这时会返回一个IBinder类,这个类个人觉得很想代理模式,通过它来调用service中的方法,在我们bindservice的时候,需要传入一个参数,ServiceConnection,在这个对象里面有两个回调方法,一个是ublic void onServiceConnected(ComponentName name, IBinder service)一个是public void onServiceDisconnected(ComponentName name),在onServiceConnected中的参数service就是我们在onBind方法中返回的IBinder,通过对它的转型,我们就可以调用相应的service中的方法了。所以这里我写了一个内部类NormalBinder,用它来打印“”bind method”并在onBind方法中返回他,这样我在MainActivity中就可以得到这个NormalBinder,并调用它内部的方法。

public class NormalService extends Service {       public NormalService() {    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        System.out.println("service start");        stopSelf();        return super.onStartCommand(intent, flags, startId);    }    @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.        NormalBinder normalBinder=new NormalBinder();        return normalBinder;    }    @Override    public void onDestroy() {        super.onDestroy();        System.out.println("stop service");    }    public class NormalBinder extends Binder    {           public void bindMethod()        {            System.out.println("bind method");        }    }}

对于这个流程,我本想画个示意图,但是太懒了,我决定还是文字吧。

跨进程通讯的方式有两种,一种是AIDL,一种就是利用Messenger了,这两种方式的区别就在鱼AIDL是多线程的,而Messenger是单线程的,也就是说利用Messenger的跨进程通信在消息队列中每次只有一个请求。需要注意的是如果你需要服务器回传数据给客户端,你需要在handler的public void handleMessage(Message msg)方法中得到客户端的Messenger,这个messenger就是Messenger clientMessenger=msg.replyTo;这是在客户端在向服务端发送Message的时候传递给message的参数。

public class ServerService extends Service {       private Handler handler=new Handler()    {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if(msg.what==233)            {                Messenger clientMessenger=msg.replyTo;                Message message=new Message();                message.what=322;                try {                    clientMessenger.send(message);                } catch (RemoteException e) {                    e.printStackTrace();                }            }        }    };    private Messenger messenger=new Messenger(handler);    public ServerService()    {    }    @Override    public void onCreate() {        super.onCreate();        System.out.println("service create");    }    @Override    public IBinder onBind(Intent intent) {        System.out.println("bind service");       return messenger.getBinder();    }}

接着MainAcitivyt发起bindService的请求,(这里要注意的是,5.0以后,开启service的Intent必需是显示的Intent,所以你的Intent里必须要包含另一个程序的包名的信息。)在ServiceConnection中的onServiceConnected的方法里,通过返回的IBinder来得到相应的Messenger

private ServiceConnection messengerConnection=new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            hasBound=true;            serverMessenger=new Messenger(service);            Message message=new Message();            message.what=233;            message.replyTo=clientMessenger;            try {                serverMessenger.send(message);            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName name) {          hasBound=false;        }    };

转载地址:http://jbls.baihongyu.com/

你可能感兴趣的文章
NIFI大数据进阶_FlowFile生成器_GenerateFlowFile处理器_ReplaceText处理器_实际操作---大数据之Nifi工作笔记0020
查看>>
NIFI大数据进阶_Json内容转换为Hive支持的文本格式_实际操作_02---大数据之Nifi工作笔记0032
查看>>
NIFI大数据进阶_Json内容转换为Hive支持的文本格式_操作方法说明_01_EvaluteJsonPath处理器---大数据之Nifi工作笔记0031
查看>>
NIFI大数据进阶_Kafka使用相关说明_实际操作Kafka消费者处理器_来消费kafka数据---大数据之Nifi工作笔记0037
查看>>
NIFI大数据进阶_Kafka使用相关说明_实际操作Kafka生产者---大数据之Nifi工作笔记0036
查看>>
NIFI大数据进阶_NIFI的模板和组的使用-介绍和实际操作_创建组_嵌套组_模板创建下载_导入---大数据之Nifi工作笔记0022
查看>>
NIFI大数据进阶_NIFI监控功能实际操作_Summary查看系统和处理器运行情况_viewDataProvenance查看_---大数据之Nifi工作笔记0026
查看>>
NIFI大数据进阶_NIFI监控的强大功能介绍_处理器面板_进程组面板_summary监控_data_provenance事件源---大数据之Nifi工作笔记0025
查看>>
NIFI大数据进阶_NIFI集群知识点_认识NIFI集群以及集群的组成部分---大数据之Nifi工作笔记0014
查看>>
NIFI大数据进阶_NIFI集群知识点_集群的断开_重连_退役_卸载_总结---大数据之Nifi工作笔记0018
查看>>
NIFI大数据进阶_使用NIFI表达式语言_来获取自定义属性中的数据_NIFI表达式使用体验---大数据之Nifi工作笔记0024
查看>>
NIFI大数据进阶_内嵌ZK模式集群1_搭建过程说明---大数据之Nifi工作笔记0015
查看>>
NIFI大数据进阶_外部ZK模式集群1_实际操作搭建NIFI外部ZK模式集群---大数据之Nifi工作笔记0017
查看>>
NIFI大数据进阶_实时同步MySql的数据到Hive中去_可增量同步_实时监控MySql数据库变化_操作方法说明_01---大数据之Nifi工作笔记0033
查看>>
NIFI大数据进阶_实时同步MySql的数据到Hive中去_可增量同步_实时监控MySql数据库变化_操作方法说明_02---大数据之Nifi工作笔记0034
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_01_实际操作---大数据之Nifi工作笔记0029
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_说明操作步骤---大数据之Nifi工作笔记0028
查看>>
NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
查看>>
NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
查看>>