博客
关于我
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从MySql中离线读取数据再导入到MySql中_03_来吧用NIFI实现_数据分页获取功能---大数据之Nifi工作笔记0038
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_不带分页处理_01_QueryDatabaseTable获取数据_原0036---大数据之Nifi工作笔记0064
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_无分页功能_02_转换数据_分割数据_提取JSON数据_替换拼接SQL_添加分页---大数据之Nifi工作笔记0037
查看>>
NIFI从PostGresql中离线读取数据再导入到MySql中_带有数据分页获取功能_不带分页不能用_NIFI资料太少了---大数据之Nifi工作笔记0039
查看>>
nifi使用过程-常见问题-以及入门总结---大数据之Nifi工作笔记0012
查看>>
NIFI分页获取Mysql数据_导入到Hbase中_并可通过phoenix客户端查询_含金量很高的一篇_搞了好久_实际操作05---大数据之Nifi工作笔记0045
查看>>
NIFI分页获取Postgresql数据到Hbase中_实际操作---大数据之Nifi工作笔记0049
查看>>
NIFI同步MySql数据_到SqlServer_错误_驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server_Navicat连接SqlServer---大数据之Nifi工作笔记0047
查看>>
NIFI同步MySql数据源数据_到原始库hbase_同时对数据进行实时分析处理_同步到清洗库_实际操作06---大数据之Nifi工作笔记0046
查看>>
Nifi同步过程中报错create_time字段找不到_实际目标表和源表中没有这个字段---大数据之Nifi工作笔记0066
查看>>
NIFI大数据进阶_FlowFile拓扑_对FlowFile内容和属性的修改删除添加_介绍和描述_以及实际操作---大数据之Nifi工作笔记0023
查看>>
NIFI大数据进阶_FlowFile生成器_GenerateFlowFile处理器_ReplaceText处理器_处理器介绍_处理过程说明---大数据之Nifi工作笔记0019
查看>>
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
查看>>