Android Studio 新建线程Thread进行后台(背景)音频(MP3)播放,并随时切换音频的实现方法

一、前言

最近在做盲人导航,需要根据周围的环境不断在后台播放提示语音。查了下资料,找到一个效果还可以的源码。

二、思路概括

1.把要播放的曲目通过mp3的格式放在src的raw文件夹里,这样可以通过R.raw.xxx获得相应的ID。
2.新建一个全局变量MusicName,用于存放需要播放的声音的名字。
3.新建一个在后台运行的线程,随时播放声音,播放的曲目根据全局变量MusicName的改变而改变。

这样一来,在程序的某个位置改变MusicName时,就可以改变背景音乐,实现实时提示的效果,且不影响主线程的运行。

三、实现方法

1.建立全局变量

用public class的方法新建一个全局变量,我这里命名为MusicName,方便其他activity随时指定。注意这个全局变量的数据类型是int,因为通过R.raw.xxx方式制定的MP3路径是int格式的。
在这里插入图片描述
注意把第一行package的路径改为自己的。

//路径改为自己的
package com.example.myapplication;

public class MusicName {
    private static int name = 0;

    public static int getName() {
        return name;
    }

    public static void setName(int name) {
        MusicName.name = name;
    }
}

2.建立一个AudioService 的类

新建一个名为AudioService 的类。代码如下。

//package 改为自己的路径
package com.example.myapplication;

import android.app.Service;

/**
 * 多线程实现后台播放背景音乐的service
 */
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;

public class AudioService extends Service implements
        MediaPlayer.OnCompletionListener {
    // 实例化MediaPlayer对象
    MediaPlayer player;
    private final IBinder binder = new AudioBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    public void onCreate() {
        super.onCreate();
        // 从raw文件夹中获取一个应用自带的mp3文件
        player = MediaPlayer.create(this, R.raw.silent);
        player.setOnCompletionListener(this);
        player.setLooping(true);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        if (!player.isPlaying()) {
            new MusicPlayThread().start();
        } else
            player.isPlaying();
        return START_STICKY;
    }

    /**
     * 当Audio播放完的时候触发该动作
     */
    public void onCompletion(MediaPlayer mp) {
        stopSelf();// 结束了,则结束Service

    }

    public void onDestroy() {
        super.onDestroy();
        if (player.isPlaying()) {
            player.stop();
        }
        player.release();
    }

    // 为了和Activity交互,我们需要定义一个Binder对象
    public class AudioBinder extends Binder {
        // 返回Service对象
        public AudioService getService() {
            return AudioService.this;
        }
    }

    private class MusicPlayThread extends Thread {
        public void run() {
            if (!player.isPlaying()) {
                player.start();
            }
        }
    }

}

注意:
(1)直接复制的话,要把第一行package的路径改为自己的。
(2)代码要求SDK最低版本是21。
(3)由于代码设计逻辑不够完善,最开始要制定一段空白音乐给系统播放。

player = MediaPlayer.create(this, R.raw.silent);

这段空白音频我放在这里了,大家可以下载一下。
链接:https://pan.baidu.com/s/1kaIAJpxJff-V0XvpS62u3g
提取码:24gi

3.在你的activity中建立一个线程,放入播放音乐的函数

在某个Activity的onCreate函数建立线程,以及在public class的层级加入playBGsound()函数。总共两部分,在你的代码中加入注释中的部分即可。直接复制的话,注意我的activity命名是"MainActivity_rs",要改成自己的。

public class MainActivity_rs extends AppCompatActivity {

	//************加入部分1**********
	MediaPlayer mp=null;//声明一个MediaPlayer对象
    private void playBGSound(){
        if(mp!=null){
            mp.release();//释放资源
        }
        while (MusicName.getName()==0);
        //播放的曲目取决于MusicName的值
        mp=MediaPlayer.create(MainActivity_rs.this, MusicName.getName());
        mp.start();
        //为MediaPlayer添加播放完成事件监听
        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                try {
                    Thread.sleep(10);//暂停时间(毫秒)
                    playBGSound();//重新播放音乐
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        });
    }
    //************加入部分1**********

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //这个layout是我自己的,不要直接复制
        setContentView(R.layout.activity_main_rs);
        
        //************加入部分2**********
		Thread music_thread;//声明一个线程对象
        music_thread = new Thread(new Runnable() {
            @Override
            public void run() {
                playBGSound();//播放背景音乐
            }
        });
        music_thread.start();//开启线程
        //************加入部分2**********
        
    }
}

4.动态改变播放的音乐

大功告成!系统此时应该就会开始不间断地播放声音了。由于默认播放的是空白音乐(意味着没声音),因此需要在程序运行中人为指定。例如,要想改变播放的音频,可以这样操作:

MusicName.setName(R.raw.left60_fast);

由于播放后台音乐的线程会不断读取全局变量MusicName的值,因此当MusicName改变时,播放音乐也会随之改变。注意这里的R.raw.left60_fast是我个人的音频,大家可以替换为其他的MP3。

5.停止播放的方法

解决方法:stopService()和stopSelf()都可以停止通过startService()方式启动的service。stopService需要传递startService(Intent
service)时的intent对象作为参数,停止此intent对应的service。stopSelf直接停止本service,不需要参数,在service中直接调用即可。

6.附:目录结构

标红的地方是需要改动的。注意我是在MainActivity_rs中改动的,大家也可以换成其他的activity。
在这里插入图片描述

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值