Android使用Service及BroadcastReceiver实现音乐播放器

播放音乐,我们需要在AndroidManifest.xml文件添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

创建Service,需要在AndroidManifest.xml文件配置

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

现在我们创建了一个叫做MusicService的Service,它是继承Service类的

话不多说,先看看效果图

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/songName"
        android:text="打击乐器"
        android:textSize="15sp"
        android:layout_marginTop="5dp"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/img"
        android:id="@+id/Image"
        android:layout_gravity="center" />

    <!--显示歌曲状态-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:id="@+id/MusicStatus"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:gravity="center_horizontal">

        <!--显示当前进度-->
        <TextView
            android:id="@+id/MusicTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="00:00" />

        <SeekBar
            android:layout_width="230sp"
            android:layout_height="wrap_content"
            android:id="@+id/MusicSeekBar"
            android:layout_weight="1"
            android:max="100"
            android:layout_toRightOf="@+id/MusicTime"/>

        <!--显示总进度-->
        <TextView
            android:id="@+id/MusicTotal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="00:16"
            android:layout_toRightOf="@+id/MusicSeekBar"/>

    </RelativeLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal">

        <Button
            android:id="@+id/BtnPrev"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="15dp"
            android:background="@drawable/shape"
            android:text="PREV"
            android:textAllCaps="false"
            android:textColor="@color/colorWhite" />

        <Button
            android:id="@+id/BtnPlayorStop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/shape"
            android:layout_marginRight="15dp"
            android:text="PLAY"
            android:textAllCaps="false"
            android:textColor="@color/colorWhite" />

        <Button
            android:id="@+id/BtnNext"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/shape"
            android:text="NEXT"
            android:textAllCaps="false"
            android:textColor="@color/colorWhite" />
    </LinearLayout>

</LinearLayout>

Activity部分代码:

package com.example.ch8;

import androidx.appcompat.app.AppCompatActivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    //定义音乐播放状态,0x10代表上一首,0x11代表没有播放或暂停,0x12代表正在播放,0x13代表下一首,0x15表示暂停
    int status = 0x11;
    static long mediaPlayerDuration = 1L;
    static int sum=0;
    //三个按钮
    Button prve,playorpause,next;
    static SeekBar seekBar;
    //歌曲名
    static TextView songname,starttime,endtime;
    ActivityReceiver mActivityReceiver;

    String[] name=new String[]{"打击乐器","康加舞","蓝调小号","手拍鼓"};
    public static final String CTL_ACTION = "com.trampcr.action.CTL_ACTION";
    public static final String UPDATE_ACTION = "com.trampcr.action.UPDATE_ACTION";

    //运用Handler中的handleMessage方法接收service传递的音乐播放进度信息
    public static Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            // super.handleMessage(msg);
            // 将SeekBar位置设置到当前播放位置,
            // msg.arg1是service传过来的音乐播放进度信息,将其设置为进度条进度
            seekBar.setProgress(msg.arg1/((int)(mediaPlayerDuration*10)));
            //将进度时间其转为mm:ss时间格式
            starttime.setText(new SimpleDateFormat("mm:ss", Locale.getDefault()).format(new Date(msg.arg1)));
            return false;
        }
    });
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        songname=findViewById(R.id.songName);
        starttime=findViewById(R.id.MusicTime);
        endtime=findViewById(R.id.MusicTotal);
        prve=findViewById(R.id.BtnPrev);
        playorpause=findViewById(R.id.BtnPlayorStop);
        next=findViewById(R.id.BtnNext);
        seekBar=findViewById(R.id.MusicSeekBar);

        prve.setOnClickListener(this);
        playorpause.setOnClickListener(this);
        next.setOnClickListener(this);

        mActivityReceiver = new ActivityReceiver();
        //创建IntentFilter
        IntentFilter filter = new IntentFilter();
        //指定BroadcastReceiver监听的Action
        filter.addAction(UPDATE_ACTION);
        //注册BroadcastReceiver
        registerReceiver(mActivityReceiver, filter);

        Intent intent = new Intent(MainActivity.this, MusicService.class);
        //启动后台Service
        startService(intent);
        Log.i("1","启动服务");

    }

    //接收service的消息
    public class ActivityReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            //获取Intent中的update消息,update代表播放状态
            int update = intent.getIntExtra("update", -1);
            //获取Intent中的current消息,current代表当前正在播放的歌曲
            int current = intent.getIntExtra("current", -1);
            int pro=intent.getIntExtra("process",-1);
            mediaPlayerDuration=intent.getLongExtra("endtime",-1);
            seekBar.setProgress(pro);
            String time=null;
            if(mediaPlayerDuration<10){
                time="0"+mediaPlayerDuration;
            }
            else {
                time=""+mediaPlayerDuration;
            }
            songname.setText(name[current]);
            switch (update){
                case 0x11:
                    playorpause.setText("PLAY");
                    endtime.setText("00:"+time);
                    status = 0x11;
                    break;
                //控制系统进入播放状态
                case 0x12:
                    //在播放状态下设置使用暂停图标
                    playorpause.setText("PAUSE");
                    endtime.setText("00:"+time);
                    status = 0x12;
                    break;
                case 0x15:
                    playorpause.setText("PLAY");
                    endtime.setText("00:"+time);
                    status = 0x15;
                    break;
            }
        }
    }

    @Override
    public void onClick(View v) {
        Intent intent = new Intent(CTL_ACTION);
        Log.i("1","发送消息");
        switch (v.getId()){
            case R.id.BtnPrev:
                intent.putExtra("control", 1);
                break;
            case R.id.BtnPlayorStop:
                if(status==0x11||status==0x15){
                    intent.putExtra("control", 2);
                }
                else if(status==0x12){
                    intent.putExtra("control", 3);
                }
                break;
            case R.id.BtnNext:
                intent.putExtra("control", 4);
                break;
        }

        //发送广播,将被Service中的BroadcastReceiver接收到
        sendBroadcast(intent);
    }


}
MusicService部分代码:
package com.example.ch8;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

import java.util.Timer;
import java.util.TimerTask;

public class MusicService extends Service{
    long mediaPlayerDuration = 0L;
    MyReceiver serviceReceiver;
    AssetManager am;

    int[] musics1=new int[]{R.raw.music1,R.raw.music2,R.raw.music3,R.raw.music4};
    static MediaPlayer mPlayer;
    //定义音乐播放状态,0x10代表上一首,0x11代表没有播放,0x12代表正在播放,0x13代表下一首,0x15表示暂停
    int status = 0x11;
    //记录当前正在播放的音乐
    static int current = 0;

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("1","服务创建");
        am = getAssets();
        //创建BroadcastReceiver
        serviceReceiver =new MyReceiver();
        //创建IntentFilter
        IntentFilter filter = new IntentFilter();
        filter.addAction(MainActivity.CTL_ACTION);
        registerReceiver(serviceReceiver, filter);
        //创建MediaPlayer
        mPlayer = new MediaPlayer();

    }

    private void prepareAndPlay(int mus) {
        // TODO Auto-generated method stub
        try {
            mPlayer=MediaPlayer.create(this,mus);
            //为MediaPlayer播放完成事件绑定监听器
            mPlayer.setOnCompletionListener(new OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    //Log.d("tag", "播放完毕");
                    current++;
                    status=0x12;
                    if(current >=4){
                        current = 0;
                    }
                    //准备并播放音乐
                    prepareAndPlay(musics1[current]);
                    mediaPlayerDuration=mPlayer.getDuration()/1000;
                    //发送广播通知Activity更改文本框
                    Intent sendIntent = new Intent(MainActivity.UPDATE_ACTION);
                    sendIntent.putExtra("update", status);
                    sendIntent.putExtra("current", current);
                    sendIntent.putExtra("endtime",mediaPlayerDuration);
                    //发送广播,将被Activity组件中的BroadcastReceiver接收到
                    sendBroadcast(sendIntent);
                }
            });
            //播放
            mPlayer.start();
            //每隔500毫秒发送音乐进度
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    //实例化一个Message对象
                    Message msg = Message.obtain();
                    //Message对象的arg1参数携带音乐当前播放进度信息,类型是int
                    msg.arg1 = mPlayer.getCurrentPosition();
                    //使用MainActivity中的handler发送信息
                    MainActivity.handler.sendMessage(msg);
                }
            }, 0, 500);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    public class MyReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            int control = intent.getIntExtra("control", -1);
            switch (control) {
                case 1:
                    //上一首
                    if(mPlayer.isPlaying()){
                        mPlayer.stop();
                    }
                    int t=mPlayer.getCurrentPosition();
                    Log.i("11",""+t);
                    if(t>2000)
                        current--;
                    if(current <0){
                        current = 3;
                    }
                    prepareAndPlay(musics1[current]);
                    mediaPlayerDuration=mPlayer.getDuration()/1000;
                    status = 0x12;

                    break;
                case 2:
                    //原来处于没有播放状态
                    if(status == 0x11||!mPlayer.isPlaying()){
                        prepareAndPlay(musics1[current]);
                        mediaPlayerDuration=mPlayer.getDuration()/1000;
                        status = 0x12;
                    }
                    else if(status==0x15){
                        mPlayer.start();
                        status = 0x12;
                    }

                    break;
                case 3:
                    //正在播放
                    if(status ==  0x12){
                        //暂停播放
                        mPlayer.pause();
                        mediaPlayerDuration=mPlayer.getDuration()/1000;
                        status=0x15;
                    }
                    break;
                case 4:
                    //下一首
                    if(mPlayer.isPlaying()){
                        mPlayer.stop();
                    }
                    current++;
                    Log.i("1",current+"");
                    if(current >=4){
                        current = 0;

                    }
                    prepareAndPlay(musics1[current]);
                    mediaPlayerDuration=mPlayer.getDuration()/1000;
                    status = 0x12;
                    break;
            }
            //广播通知Activity更改图标,文本框
            Intent sendIntent = new Intent(MainActivity.UPDATE_ACTION);
            sendIntent.putExtra("update", status);
            sendIntent.putExtra("current", current);
            sendIntent.putExtra("endtime",mediaPlayerDuration);
            //发送广播,将被Activity组件中的BroadcastReceiver接收到
            sendBroadcast(sendIntent);
        }

    }
    //获取播放进度
    private long getCurrentPosition(){
        if(mPlayer.isPlaying()){
            return mPlayer.getCurrentPosition();
        }
        return 0;
    }


}

activity和MusicService部分,它们有内部类ActivityReceiver,MyReceiver继承自BroadcastReceiver,接收和发送来自各自的消息,用来互相通信

MusicService部分有一个定时器,用来定时计算音乐播放进度,并发送消息给activity

activity里有一个Handler来接收MusicService的定时器发送过来的消息,并在前台设置进度显示

mPlayer.getCurrentPosition();是获取播放实时进度的方法
mPlayer.getDuration()是获取音乐文件总时长

他们返回的都是一个整型整数

原创文章 10 获赞 10 访问量 132

猜你喜欢

转载自blog.csdn.net/weixin_41553587/article/details/105840469