zoukankan      html  css  js  c++  java
  • startService和onBinderService混合开发音乐播放器

    首先你你需要知道MediaPlayer这个类的一些方法:

    • int getDuration():获取流媒体的总播放时长,单位是毫秒。
    • int getCurrentPosition():获取当前流媒体的播放的位置,单位是毫秒。
    • void seekTo(int msec):设置当前MediaPlayer的播放位置,单位是毫秒。
    • void setLooping(boolean looping):设置是否循环播放。
    • boolean isLooping():判断是否循环播放。
    • boolean isPlaying():判断是否正在播放。
    • void prepare():同步的方式装载流媒体文件。
    • void prepareAsync():异步的方式装载流媒体文件。
    • void release ():回收流媒体资源。
    • void setAudioStreamType(int streamtype):设置播放流媒体类型。
    • void setWakeMode(Context context, int mode):设置CPU唤醒的状态。
    • setNextMediaPlayer(MediaPlayer next):设置当前流媒体播放完毕,下一个播放的MediaPlayer。

    注意一下两点

    1. 在使用MediaPlayer播放一段流媒体的时候,需要使用prepare()或prepareAsync()方法把流媒体装载进MediaPlayer,才可以调用start()方法播放流媒体。                 
    2. setAudioStreamType()方法用于指定播放流媒体的类型,它传递的是一个int类型的数据,均以常量定义在AudioManager类中, 一般我们播放音频文件,设置为AudioManager.STREAM_MUSIC即可。

    在播放下一首歌曲的时候需要释放MediaPlayer的资源:

    if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
    

    然后就是关于BinderService:

    • 先看一下按下Back键之后Activity的生命周期:onPause()-->onStop()-->onDestory()-->onCreate()-->onStart()-->onResum();

    • BinderService的存活于绑定的Activity有关,当与之绑定的Activity被销毁的时候,Service也会销毁,根据生命周期,我们就可以知道,当你按下Back键的时候,Service也会销毁,这样音乐就会停止播放,但是我们使用的大多数音乐播放器软件都按下Back键之后依旧在播放,所以,就有了我们的startServuce()和binderService()混合开发,因为startService()的生命周期与activity无关。

    • 我们的主要逻辑是,用startService播放音乐,用binderService()控制音乐的播放。

    • startService很常见,就不说了,你需要知道binderService的使用,其实binderService就是用一个继承与BInder的MyBinder的类,作为一个中间对象,在Activity中对Service中的方法进行调用,从而实现控制。

    下面我们开始编写我们的音乐播放器

    创建一个MusicItem类记录一些音乐的信息

    public class MusicItem {
        public String name;
        public String data;
        public String artist;
        public long time;
    }
    

    请求读写权限并且获取手机上的所有音频文件

    private void initData(){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (PackageManager.PERMISSION_DENIED == checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)){
                    requestPermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},0);
                }
            }
    
            itemList = new ArrayList<>();
    
            new Thread(){
                @Override
                public void run() {
                    super.run();
                    ContentResolver resolver = mContext.getContentResolver();
                    Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    String[] objs ={
                            MediaStore.Audio.Media.DISPLAY_NAME,
                            MediaStore.Audio.Media.DATA,
                            MediaStore.Audio.Media.ARTIST,
                            MediaStore.Audio.Media.DURATION,
                    };
    
                    Cursor cursor = resolver.query(uri,objs,null,null,null);
                    if (cursor !=null){
                        while (cursor.moveToNext()){
                            MusicItem musicItem = new MusicItem();
                            itemList.add(musicItem);
    
                            String name = cursor.getString(0);
                            musicItem.name = name;
                            String data = cursor.getString(1);
                            musicItem.data = data;
                            String aritst = cursor.getString(2);
                            musicItem.artist = aritst;
                            long time = cursor.getLong(3);
                            musicItem.time = time;
                        }
                      cursor.close();
                    }
                    handler.sendEmptyMessage(0);
                }
            }.start();
    
        }
    

    获取到手机上的所有的音频文件之后,发送一个handler消息,将musicItem的集合itemList中的数据显示在Adapter上(Adapter的代码这里不拿出来说了,很见到的)

    创建一个MusicService类,继承与Service

    这个类用来后台播放音乐

    public class MusicService extends Service {
    
        private MediaPlayer player;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return new MyBinder();
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
        }
    
        public void onPause(){
            player.pause();
        }
        
        public void onStart(){
            player.start();
        }
        
        public void openAudio(String uri) throws IOException {
            if (player != null && player.isPlaying()){
                player.stop();
                player.release();
                player = null;
            }
            player = new MediaPlayer();
            player.setAudioStreamType(AudioManager.STREAM_MUSIC);
            try {
                player.setDataSource(uri);
                player.prepare();
                player.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        public class MyBinder extends Binder{
            MusicService getService(){
                return MusicService.this;
            }
        }
        @Override
        public void onDestroy() {
            super.onDestroy();
            player.stop();
            player.reset();
            player.release();
        }
    }
    
    • MyBinder是Activity与MusicService进行通信的中间对象(这里只实现了播放和暂停的功能)

    绑定MusicSerivce

    下面是Activity的onCreate()方法:

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            mContext = this;
    
            lvList = (ListView) findViewById(R.id.lv_list);
            Button start = (Button) findViewById(R.id.start);
            Button pasue = (Button) findViewById(R.id.pause);
            pasue.setOnClickListener(this);
            start.setOnClickListener(this);
            Intent intent = new Intent(MainActivity.this,MusicService.class);
            startService(intent);
            bindService(intent,conn,BIND_AUTO_CREATE);
            initData();
        }
    

    绑定Service:

    private ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                service1 = ((MusicService.MyBinder) service).getService();
            }
    
            @Override
    
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };
    

    点击ListView中的Item的时候播放音乐

    实现暂停和播放:

    private android.os.Handler handler = new android.os.Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (itemList != null && itemList.size()>0){
                    MusicAdapter adapter = new MusicAdapter(mContext,itemList);
                    lvList.setAdapter(adapter);
                    lvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                            try {
                                service1.openAudio(itemList.get(position).data);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            }
        };
    
    @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.start:
                    service1.onStart();
                    break;
    
                case R.id.pause:
                    service1.onPause();
                    break;
    
            }
        }
    
    • 当绑定成功的时候,返回的是一个MusicService对象,拿着这个Service对象就能对MusicService中的方法进行调用了。
    • 首先startService,然后在binderService让Activity与Service之间进行通信,然Activity通过MyBinder对象对Service中的方法进行调用。

    Service的销毁

    在Activity中的onDestory()方法中对MusicService进行取消绑定:

    @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(conn);
        }
    

    记得添加读写权限

    GitHub:https://github.com/godfunc
    博客园:http://www.cnblogs.com/godfunc
    Copyright ©2019 Godfunc
  • 相关阅读:
    中台入门系列1
    微服务 2.0 技术栈选型手册
    mysql计划任务每天定时执行
    更高效地提高redis client多线程操作的并发吞吐设计
    azure之MSSQL服务性能测试
    .NET Socket服务编程之-高效连接接入编
    轻易实现基于linux或win运行的聊天服务端程序
    零配置Socket TCP消息通讯服务容器EC
    azure存储压测的问题(农码主观意识太强被坑了)
    业务逻辑层缓存应该设计
  • 原文地址:https://www.cnblogs.com/Godfunc/p/6551294.html
Copyright © 2011-2022 走看看