Android 音乐盒完整版

本文介绍了一个基于Android平台的音乐服务应用实例,详细展示了如何通过自定义Service来实现音乐播放、暂停、继续播放及进度更新等功能,并通过Binder机制实现了Activity与Service之间的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class MusicService extends Service {
    private static final String TAG = "jojo";
    private MediaPlayer mediaPlayer;

    @Override
    public void onCreate() {
        //1 初始化mediaPlayer
        mediaPlayer = new MediaPlayer();
        super.onCreate();
    }

    // 把我们定义的中间人对象返回
    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }
    // 播放音乐的方法
    public void playMusic() {
        // TODO: 2017/4/27 等撸完多媒体 再完善这个案例
        //2 设置要播放的资源位置 path 可以是网络 路径 也可以是本地路径
        try {
            mediaPlayer.reset();
            mediaPlayer.setDataSource(Environment.getExternalStorageDirectory().getPath() + "/1.mp3");
            //3 准备播放
            mediaPlayer.prepare();
            //4 开始播放
            mediaPlayer.start();
            //5 更新进度条
            updateSeekBar();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //更新进度条的方法
    private void updateSeekBar() {
        //1 获取当前播放的总长度
        final int duration = mediaPlayer.getDuration();
        //2 使用Timer 定时器去定时截取当前进度
        final Timer timer = new Timer();
        final TimerTask task = new TimerTask() {
            @Override
            public void run() {
                //3 一秒钟获取一次当前进度
                int currentPosition = mediaPlayer.getCurrentPosition();
                //4 拿着我们在MainActivity创建的handler发消息 消息就可以携带数据
                Message msg = Message.obtain();
                Bundle bundle = new Bundle(); // map
                bundle.putInt("duration", duration);
                bundle.putInt("currentPosition", currentPosition);
                msg.setData(bundle);
                // 发送一条消息 mainActivity里面的handleMessage方法就会执行
                MainActivity.handler.sendMessage(msg);
            }
        };
        // 100 毫秒后 每隔1秒执行一次run方法
        timer.schedule(task, 100, 1000);
        // 当歌曲执行完毕后 把timer和timertask取消
        // 设置播放完成的监听
        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                Log.d(TAG, "onCompletion:  歌曲播放完成了");
                // 把 timer 和 timertask 取消
                timer.cancel();
                task.cancel();
            }
        });
    }
    // 暂停音乐的方法
    public void pauseMusic() {
        mediaPlayer.pause();
    }
    //继续播放音乐的方法
    public void rePlayMusic() {
        mediaPlayer.start();
    }
    //实现指定播放的位置
    public void seekTo(int position) {
        mediaPlayer.seekTo(position);
    }

    //1 在服务的内部定义一个中间人对象(IBinder)
    private class MyBinder extends Binder implements Iservice{
        //调用播放音乐的方法
        @Override
        public void callPlayMusic() {
            playMusic();
        }
        //调用暂停音乐的方法
        @Override
        public void callPauseMusic() {
            pauseMusic();
        }
        //调用继续播放音乐的方法
        @Override
        public void callRePlayMusic() {
            rePlayMusic();
        }
        @Override
        public void callSeekTo(int position) {
            seekTo(position);
        }
    }
}

public interface Iservice {
    //把想暴露的方法都定义在接口
    public void callPlayMusic();
    public void callPauseMusic();
    public void callRePlayMusic();
    public void callSeekTo(int position);
}
public class MainActivity extends AppCompatActivity {

    private Iservice iservice; // 这个是我们定义的中间人对象
    private MyConn conn;
    private static SeekBar sbar;

    public static Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // 获取我们携带的数据
            Bundle data = msg.getData();
            // 获取歌曲的总时长和当前进度
            int duration = data.getInt("duration");
            int currentPosition = data.getInt("currentPosition");
            // 设置seekBar的进度
            sbar.setMax(duration);
            sbar.setProgress(currentPosition);
        }
    };

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

        // 混合方式开启服务
        //1 先调用startService 目的是可以保证服务在后台长期运行
        Intent intent = new Intent(this, MusicService.class);
        startService(intent);
        //2 调用bingService 目的是为了获取我们定义的中间人对象 就可以间接的调用服务里面的方法了
        conn = new MyConn();
        bindService(intent, conn, BIND_AUTO_CREATE);
        //3 找到seekBar 设置进度
        sbar = (SeekBar) findViewById(R.id.seekBar1);
        //4 给seekBar设置监听事件
        sbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
           // 当进度改变的时候调用
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }
            // 开始拖动的时候调用
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }
            // 停止拖动的时候调用
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                iservice.callSeekTo(seekBar.getProgress());
            }
        });
    }

    @Override
    protected void onDestroy() {
        //当Activity销毁的时候解绑服务,目的是为了不报红色日志
        unbindService(conn);
        super.onDestroy();
    }
    //点击按钮 播放音乐
    public void click1(View v) {
        //调用播放音乐的方法
        iservice.callPlayMusic();
    }
    //点击按钮 暂停音乐
    public void click2(View v) {
        //调用暂停音乐的方法
        iservice.callPauseMusic();
    }
    //点击按钮 继续播放音乐
    public void click3(View v) {
        //调用继续播放音乐的方法
        iservice.callRePlayMusic();
    }

    //监听服务的状态
    private class MyConn implements ServiceConnection {
        //当服务连接成功时调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 获取我们的中间人对象
            iservice = (Iservice) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
}
<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.example.a68_baidumusic.MainActivity">

    <Button
        android:text="播放"
        android:onClick="click1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:text="暂停"
        android:onClick="click2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:text="继续播放"
        android:onClick="click3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
加写外存权限


相关链接:上一篇未完成的音乐盒地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值