zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    This counter can increment, decrement or skip ahead by an arbitrary amount
    LUT4/MUXF5/MUXF6 logic : Multiplexer 8:1
    synthesisable VHDL for a fixed ratio frequency divider
    Bucket Brigade FIFO SRL16E ( VHDL )
    srl16e fifo verilog
    DualPort Block RAM with Two Write Ports and Bytewide Write Enable in ReadFirst Mode
    Parametrilayze based on SRL16 shift register FIFO
    stm32 spi sdcard fatfs
    SPI bus master for System09 (2)
    SQLSERVER中的自旋锁
  • 原文地址:https://www.cnblogs.com/happyhacking/p/5318858.html
Copyright © 2011-2022 走看看