Android手机应用开发(八) | 制作简单音乐播放器

本文详细介绍了如何在Android中制作一个简单的音乐播放器。内容涵盖Service的启动和绑定、MediaPlayer的使用(包括权限申请)、Handler的运用以及时序更新UI,以及解决播放器在后台播放和停止后UI复位等问题。通过这个教程,读者可以学习到Android多媒体播放、服务管理和UI交互等关键知识点。
摘要由CSDN通过智能技术生成

实验目的

  1. 学会使用MediaPlayer
  2. 学会简单的多线程编程,使用Handler更新UI
  3. 学会使用Service进行后台工作
  4. 学会使用Service与Activity进行通信

效果预览

gif5新文件

布局

1543298569700

进度条的布局

如何实现让进度条占满当前时间全部时间中间的部分呢?

  • 如果使用match_parent,右边的全部时间又显示不了

  • 如果使用wrap_content,又不能填充满

  • 如果自定义dp值,不同尺寸显示又会不一样

这就利用了LinearLayout的特点,只需设置中间进度条的layout_weight = 1就好了,它就会自动延伸到右边最远处(不占据别的控件)

1543298911582

圆形ImageView

这里使用了github上的开源控件:链接

  1. 添加依赖implementation 'de.hdodenhof:circleimageview:2.2.0'

  2. xml中使用

    <de.hdodenhof.circleimageview.CircleImageView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/profile_image"
        android:layout_width="match_parent"
        android:layout_height="290dp"
        android:layout_marginTop="30dp"
        android:src="@drawable/img"
        app:layout_constraintTop_toTopOf="parent" />
    

Service的使用

Service(服务)是一种可以在后台执行长时间运行操作而没有用户界面的应用组件。

服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity
已销毁也不受影响。

如何启动Service

  1. 通过startService启动

    startService()启动和stopService()关闭服务,Service与访问者之间基本不存在太多关联,因此Service和访问者之间无法通讯和数据交换。

  2. 通过bindService启动

    用于Service和访问者之间需要进行方法调用或数据交换的情况

注册Service

manifests里面的application里,添加

<service android:name=".MusicService" android:exported="true"/>

创建Service

右键 -> New -> Service -> Service,取名为MusicService(跟注册时一致)

Service里添加成员

//用来跟Activity进行绑定
public final IBinder binder = new MyBinder();
//媒体播放类
public MediaPlayer mp =  new MediaPlayer();
//对Service控制的不同数字码
private final int PLAY_CODE = 1, STOP_CODE = 2, SEEK_CODE = 3, NEWMUSIC_CODE = 4, CURRENTDURATION_CODE = 5, TOTALDURATION = 6;
//重写onTransact方法,对不同的CODE做出不同的反应
public class MyBinder extends Binder {
   
        @Override
        protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
   
            switch (code) {
   
                //service solve
                case PLAY_CODE:
                    play_pause();
                    break;
                case STOP_CODE:
                    stop();
                    break;
                case SEEK_CODE:
                    mp.seekTo(data.readInt());
                    break;
                case NEWMUSIC_CODE:
                    newMusic(Uri.parse(data.readString()));
                    reply.writeInt(mp.getDuration());
                case TOTALDURATION:
                    reply.writeInt(mp.getDuration());
                    break;
                case CURRENTDURATION_CODE:
                    reply.writeInt(mp.getCurrentPosition());
                    break;
            }
            return super.onTransact(code, data, reply, flags);
        }
    }

这里的Environment.getExternalStorageDirectory()指的外部存储不是扩展卡中的存储,而是相对程序来讲,不是程序的InternalStorage,而是本机的通用存储

重写onBind方法

@Override
public IBinder onBind(Intent intent) {
   
    try {
   
            mp.setDataSource(Environment.getExternalStorageDirectory() + "/data/山高水长.mp3");
            mp.prepare();
        } catch (IOException e) {
   
            Log.e("prepare error", "getService: " + e.toString());
        }
        return binder;
}

这里返回的binder就相当于一个Service组件所返回的代理对象,Service
许客户端通过该IBinder对象来访问Service内部的数据,实现客户端与Service之间的通信

编写一些简单的控制方法

public void play_pause() {
   
        if (mp.isPlaying()) {
   
            mp.pause();
        } else {
   
            mp.start();
        }
    }
    public void stop() {
   
        if (mp != null) {
   
            mp.stop();
            try {
   
                mp.prepare();
                mp.seekTo(0);
            } catch (Exception e) {
   
                Log.d("stop", "stop: " + e.toString());
            }
        }
    }
    public void newMusic(Uri uri){
   
            try{
   
                mp.reset();
                mp.setDataSource(this, uri);
                mp.prepare();
            }
       catch (Exception e){
   
            Log.d("New Music", "new music: " + e.toString());
        }
    }

重写onDestory方法

@Override
public void onDestroy() {
   
    super.onDestroy();
    if(mp!= null){
   
        //release之前一定要r
  • 8
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值