安卓开发-Service实现音乐播放器

内容纲要

Service实现音乐播放器

用Service+MediaPlayer实现后台播放网络媒体链接,添加seekbar和button实现播放控制

创建Service

public class MusicService extends Service {
    //从网易云抓取的播放链接
    private String path = "http://m10.music.126.net/20200104135351/794ede970720b02ed8ac726c5dc6936a/ymusic/918c/1958/7d87/022d7d76c923b1caaca6e30ca47d0f69.mp3";
    private MediaPlayer player;

    public MusicService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        //当执行完了onCreate后,执行onBind把操作歌曲的方法返回,和Activity进行交互
        return new MyBinder();
    }
    @Override
    public void onCreate() {
        super.onCreate();
        //加载本地音乐
        //initLocalMusic();
        //加载网络音乐
        initNetMusic();
    }

    private void initNetMusic() {
        if (player == null){
            //如果为空就new我一个
            player = new MediaPlayer();
            try {
                player.setDataSource(path);
//                player.prepare();
                //异步准备
                player.prepareAsync();
                //添加监听
//                player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
//                    @Override
//                    public void onPrepared(MediaPlayer mp) {
//                        mp.start();
//                    }
//                });
                Log.e("myService","player prepared");
            } catch (IOException e) {
                Log.e("myService","play failed");
                e.printStackTrace();
            }
        }else {
            //判断是否处于播放状态
            if (player.isPlaying()){
                player.pause();
            }else {
                player.start();
            }
        }
    }

    private void initLocalMusic() {
        //这里只执行一次,用于准备播放器
        player = new MediaPlayer();
        try {
            player.setDataSource(path);
            //准备资源
            player.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.e("myService", "准备播放音乐");
    }

    public class MyBinder extends Binder {
        //判断是否处于播放状态
        public boolean isPlaying(){
            return player.isPlaying();
        }
        //播放或暂停歌曲
        public void play() {
            if (player.isPlaying()) {
                player.pause();
            } else {
                player.start();
            }
            Log.e("myService", "播放音乐");
        }
        //返回歌曲的长度
        public int getDuration(){
            return player.getDuration();
        }
        //返回歌曲目前的进度
        public int getCurrenPostion(){
            return player.getCurrentPosition();
        }
        //设置歌曲播放的进度
        public void seekTo(int mesc){
            player.seekTo(mesc);
        }
    }
}

Activity添加交互

public class MainActivity extends AppCompatActivity {
    private MyConnection conn;
    private MusicService.MyBinder musicControl;

    private Button btn_play;
    private SeekBar seekBar;
    //定义状态变量,更新进度条
    private static final int UPDATE_PROGRESS = 0;

    //主进程创建消息处理器handler定时更新进度条
    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_PROGRESS:
                    updateProgress();
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initService();
    }

    private void initService() {
        btn_play = (Button) findViewById(R.id.btn_play);
        seekBar = (SeekBar) findViewById(R.id.sb);

        Intent intent_music = new Intent(this, MusicService.class);
        conn = new MyConnection();

        //使用混合的方法开启服务
        startService(intent_music);
        bindService(intent_music, conn, BIND_AUTO_CREATE);

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                //进度条改变
                if (fromUser){
                    musicControl.seekTo(progress);
                }
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                //开始触摸进度条
            }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                //停止触摸进度条
            }
        });
    }

    private class MyConnection implements ServiceConnection {
        //服务启动完成后会进入到这个方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //获得service中的MyBinder
            musicControl = (MusicService.MyBinder) service;
            //更新按钮的文字
            updatePlayText();
            //设置进度条的最大值
            seekBar.setMax(musicControl.getDuration());
            Log.e("myService","最大值为"+String.valueOf(musicControl.getDuration()));
            //设置进度条的进度
            seekBar.setProgress(musicControl.getCurrenPostion());
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        //进入到界面后开始更新进度条
        if (musicControl != null){
            handler.sendEmptyMessage(UPDATE_PROGRESS);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //退出应用后与service解除绑定
        unbindService(conn);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //停止更新进度条的进度
        handler.removeCallbacksAndMessages(null);
    }

    //更新进度条
    private void updateProgress() {
        int currenPostion = musicControl.getCurrenPostion();
//        String cp = String.valueOf(currenPostion);
//        Log.e("myService","当前播放至"+cp);

        //使用Handler每500毫秒更新一次进度条
        seekBar.setMax(musicControl.getDuration());
        seekBar.setProgress(currenPostion);

        handler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 500);
    }

    //更新按钮的文字
    public void updatePlayText() {
        if (musicControl.isPlaying()) {
            btn_play.setText("暂停");
            handler.sendEmptyMessage(UPDATE_PROGRESS);
        } else {
            btn_play.setText("播放");
        }
    }
    public void mClick(View view) {
        //调用MyBinder中的play()方法
        switch (view.getId()){
            case R.id.btn_play:
                musicControl.play();
                updatePlayText();
                break;
            default:
                break;
        }
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="10dp"
                android:layout_marginRight="10dp"
                android:layout_marginBottom="10dp"
                android:layout_weight="9"
                android:text="Service实现音乐播放器"
                android:textColor="#FF9800"
                android:textSize="24sp"
                android:textStyle="italic"
                android:typeface="normal"
                app:fontFamily="sans-serif-condensed-medium" />

            <ImageView
                android:id="@+id/imageView2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                app:srcCompat="@drawable/mypic_ad" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="8"
            android:orientation="vertical">

            <SeekBar
                android:id="@+id/sb"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="horizontal">

                <Button
                    android:id="@+id/btn_play"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:onClick="mClick"
                    android:text="播放" />

            </LinearLayout>

        </LinearLayout>
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

发表评论