• android:使用Messenger进行进程间通信(二)


    //继续完善音乐播放器demo

    相关文章:
    android:使用Messenger进行进程间通信(一):http://www.cnblogs.com/happyhacking/p/5318418.html
    android:使用RemoteView自定义Notification:http://www.cnblogs.com/happyhacking/p/5318529.html

    activity => service => notification

    在添加了Notification之后,出现一个问题,即通过activity和notification都可以实现对service中方法的调用,
    然而目前两者并不能同步.由于之前已经实现了从activity到service的进程间通信,所以当在activtiy中进行操作时,
    相应的在service中使用handler更新notification的内容即可.

      class IncomingHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                mActivityMessenger = msg.replyTo;
                switch (msg.what) {
                    case 0:
                        mMediaPlayer.stop();
                        i  = msg.arg1;
                        mMediaPlayer = MediaPlayer.create(MusicService.this, mMusicDatas.get(i).getSrc());
                        if(isPlaying) {
                            mMediaPlayer.start();
                        }
    
                        //更新notification显示的内容
                        mRemoteViews.setTextViewText(R.id.music_name, mMusicDatas.get(i).getName());
                        mRemoteViews.setTextViewText(R.id.singer_name, mMusicDatas.get(i).getSinger());
                        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                        break;
                    case 1:
                        if(msg.arg1==1){
                            isPlaying =false;
                            mMediaPlayer.pause();
                              
                            //更新notification显示的内容
                            mRemoteViews.setImageViewResource(R.id.btn_play, R.drawable.note_btn_play);
                            mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                        } else {
                            isPlaying = true;
                            i = msg.arg2;
                            mMediaPlayer = MediaPlayer.create(MusicService.this, mMusicDatas.get(i).getSrc());
                            mMediaPlayer.start();
    
                            //更新notification显示的内容
                            mRemoteViews.setImageViewResource(R.id.btn_play, R.drawable.note_btn_pause);
                            mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    

    notification => service => activity

    在谷歌的官方文档中有以下描述:

    If you want the service to respond, then you need to also create a Messenger in the client. 
    Then when the client receives the onServiceConnected() callback, it sends a Message to the service 
    that includes the client's Messenger in the replyTo parameter of the send() method.
    

    个人理解是:
    要实现service到activity的通信,需要在activity(client)也创建一个Messenger,并且在onServiceConnected()
    方法中将这个messenger实例作为replyTo的参数send到service.

    activity中的处理:

    ①创建activity自身的messenger,用来处理service发送过来的message
    ②在ServiceConnection实例的onServiceConnected()回调方法中将activity的messenger作为msg.replyTo的参数send给service

       //创建activity自身的messenger
        private  Messenger mActivityMessenger = new Messenger(new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case CODE:
                        mIndex = msg.arg1;
                        setMusicNameAndSingerName(mIndex);
                        if(msg.arg2 == 1) {
                            mPlayBtn.setBackgroundResource(R.drawable.desk_pause);
                        } else {
                            mPlayBtn.setBackgroundResource(R.drawable.desk_play);
                        }
                }
            }
        });
    
    
        private ServiceConnection mServiceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mMessenger = new Messenger(service);
    
                //注意这里紧接着要send一次,目的是防止首先操作的是notification,而这时service还没有得到activity的messenger,导致service->activity的通信失败.
                Message message = Message.obtain();
                message.replyTo = mActivityMessenger;
                try {
                    mMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
        };
    

    service中的处理

    在自定义hangdler中接收activity发送过来的messenger.

     class IncomingHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                
                //获取client的messenger
                mActivityMessenger = msg.replyTo;
                
                switch (msg.what) {
                  //...
                }
            }
        }
    

    当notification中的点击事件发生时,调用以下方法,向activity发送msg

        //service->activity
        private void sendToActivity() {
            Message message = Message.obtain();
            message.what = MainActivity.CODE;
            message.arg1 = i;
            message.arg2 = (isPlaying == true)?1:2;
            try {
                mActivityMessenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    

    如此一来,就实现了activity和service之间的进程间的双向通信.

    基本原理如下图所示:

    图中:黑字实线是activity和service的绑定过程中相互发送messenger的过程.
    红字虚线是进程间相互通信的过程.

    需要强调的是:
    在bindService()成功后,要立即将activity的messenger发送给service,否则,如果在此操作之前,操作notification,
    由于此时service中还没有activity的messenger,将无法将notification的操作同步到activity中.

    github地址:https://github.com/zhangbz/MusicPlayer

  • 相关阅读:
    认证-权限-频率组件
    视图组件
    序列化类
    解析模块
    异常模块
    响应模块分析
    请求模块分析
    cbv请求分析
    django中的restful规范
    web接口与restful规范
  • 原文地址:https://www.cnblogs.com/happyhacking/p/5318858.html
Copyright © 2020-2023  润新知