1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Android多媒体应用开发之MP3音乐播放器

Android多媒体应用开发之MP3音乐播放器

时间:2019-01-19 00:12:59

相关推荐

Android多媒体应用开发之MP3音乐播放器

一,MediaPlayer类概述

MediaPlayer是ANdroid自带的多媒体库,可用于实现音频操作,若结合SurfaceView和VideoView等控件可是实现视频的播放。

1,创建MediaPlayer对象,并装载音频文件

①可以直接使用new的方式

MediaPlayer mp=new MediaPlayer();

此时,需要调用setDataSource()方法指定要播放的资源文件,调用prepare(),调用start()进行播放。

②使用create的方式

MediaPlayer mp=MediaPlayer.create(this,T.raw.test);

此时,不用调用setDataSource(),也不需要调用prepare(),可直接调用start()函数进行播放。

2,设置要播放的文件

通过setDataSource()方法

①void setDataSource(String path); 指定装载path路径所代表的文件。

②void setDataSource(FileDescriptor fd, long offset, long length); 指定装载fd所代表的文件中从offset开始、长度为length的文件内容。

③void setDataSource(FileDescroptor fd); 指定装载fd所代表的文件。

④void setDateSource(Context context, Uri uri); 指定装载Uri代表的文件。

注意:在使用setDataSource()方法装载音频文件后,实际上MediaPlayer并真正装载该音频文件,还需要调用MediaPlayer的prepare()方法真正装载音频文件。

3,播放的文件的三个来源

(1)播放应用中事先自带的resource资源

*res文件夹与assert文件夹的区别

Android中子源分为两种,

res下的可编译的资源文件,这种资源文件会在R中自动生成该资源文件的ID,直接通过R.xxx.id访问;res/raw不可以有目录结构

assets文件夹下的原生资源文件,不会被R文件编译;可以有目录结构,既是可以在assets目录下在建立文件夹。

*

Ⅰ,播放应用的资源文件

①调用MediaPlayer的create(Context context , int resid)方法加载指定资源文件

②调用MediaPlayer的start()、pause()、stop()等方法控制播放即可

MediaPlayer.create(this,R.raw.song);

Uri uri=Uri.parse("android.resource://"+this.getPackageName()+"/"+R.raw.da);player=new MediaPlayer();player.setDataSource(this,uri);player.perpare();

Ⅱ,播放应用的原始资源文件

①,调用Activity中的getAssets()方法获取应用的AssetManager

②,调用AssetManager对象的openFd(STring name)方法打开指定的原生资源,该方法返回一个AssetFileDescriptor对象。

③,调用AssetFileDescriptor的getFileDescriptor()和getLength()方法来获取音频文件的FileDescriptor、开始位置、长度

④,创建MediaPlayer对象,并调用MediaPlayer对象的setDataResource(FileDescriptor fd,long offeset,long length)方法来装在音频资源

⑤,调用MediaPlayer对象的prepare()方法准备音频

⑥,调用MediaPlayer的start(),pause()、stop()等方法控制播放即可。

🔺(2)存储在SD卡或其他文件路径下的媒体文件

①创建MediaPlayer对象,并调用MediaPlayer对象的setDataSource(String path)方法装载指定音频文件

②调用MediaPlayer对象的prepare()方法准备音频

③调用MediaPlayer的start()、stop()等方法控制播放即可

player = new MediaPlayre();player.setDataSource("/sdcard/pm.mp3");//或//paler.setDataSource(Environment.getExternalStorageDirectory()+"/pm.mp3);player.prepare();

注意:对sdcard的访问需要在AndroidManifest.xml中设置相应的权限

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

在安卓23.0版本以上,还需要动态申请权限

//判断是否6.0以上的手机if(Build.VERSION.SDK_INT>=23){//判断是否有这个权限int permmission=ActivityCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE);//checkSelfPremission检查对应的权限是否打开,如果是PackageManager.PERMISSION_GRANTED表示打开if(permission!=PackageManager.PERMISSION_GRANTED){//请求权限ActivityCompat.requestPermissions(this,new String[]{Manifes.permission.READ_EXTERNAL_STORAGE},ECTERNAL_STORAGE_REQ_CODE);}

(3)网络上的媒体文件

①直接使用create(Context context ,Uri uri)

MediaPlayer mp=MediaPlayer.create(this,Uri.parse(/music/m1.mp3))

②调用setDataSource(Context context,Uri uri)

mp.setDataSource(this,Uri.parse("htp:///music/m1.mp3"));

此时,需要在AndroidManifest.xml中授权程序访问网络的权限

<users-permission android:name="android.permission.INTERNET"/>

4,对播放器的主要控制方法

①prepare():同步

同步的为播放器的回放做准备,设置数据源和显示表面后调用;对于文件,可以调用prepare(),它会阻塞,直到MediaPlayer准备好播放为止。

②prepareAsync():异步

异步的为播放器的回放做准备。设置好数据源和显示表面后调用。对于流,应该调用prepareAsync(),它会立即返回,而不是阻塞,直到缓冲了足够的数据。

注意:prepare()方法,是将资源同步缓存到内存中,一般加载本地较小的资源使用。如果较大的资源或网络资源建议使用prepareAsync()

▲对于异步装载考虑是否能在资源装载完成后才可以操作

需要设置监听事件setOnPreparedListener();来通知MediaPlayer资源已经获取到了,然后实现onPrepared(MediaPlayre mp)方法,在里面启动MediaPlayer

viderView.setOnPreparedListener(new OnpreparedListener(){public void onPrepared(MediaPlayer mp){mp.play();}});

5,MediaPlayer的方法

start(): 开始播放或恢复已经暂停的音频的播放

stop(): 停止正在播放的音频

pause(): 暂停正在播放的音频

void seekTo(int msec): 设置当前MediaPlayre的播放位置,可以让播放器从指定位置开始播放,单位是毫秒。

int getDuration(): 获取流媒体的总播放时长,单位是毫秒

int getCurrentPosition():获取当流媒体的播放位置,单位是毫秒

void setLooping(boolean looping); 设置是否循环播放。播放完毕后,不会回调OnCompletionListener,而是从头播放当前音频

boolean isLooping(); 判断是否循环播放

boolean isPlaying(); 判断是否正在播放

void release(); 回收流媒体资源

void setAudioStreamType(int streamtype); 设置播放流媒体类型

void setWakeMode(Context context,int mode); 设置CPU唤醒的状态

setNextMediaPlayer(MedaiPlayer next); 设置当前流媒体播放完毕,下一个播放的MediaPlayer

6,MediaPlayer的监听事件

通常在新建一个MedaiPlayer实体后,会对给它增加需要的监听事件

MediaPlayer.onPreparedListener: MediaPlayer进入准备完毕的状态出发,表示流媒体可以开始播放了

MediaPlayer.OnSeekCompleteListener: 调用MediaPlayer的seekTo方法后,MediaPlayer会跳转到媒体指定的位置,当跳转完成时触发。(注意:seekTo不能精确的跳转,它的跳转点必须是媒体资源的关键帧)

MediaPlayer.OnBufferingUpdateListener: 网络上的媒体资源缓存进度更新的时候被触发,比如在加载网络音频的时候,常用这个监听器来监听缓存进度。

MediaPlayer.OnCompletionListener: 媒体播放完毕时会触发。(由于playere占有的系统资源比较大,因此在播放结束后,就应该掉哟ing该方法,把player占有的资源给释放掉。当OnErrorLister返回false,或MediaPlayer没有设置OnErrorListener时,这个监听会发触发)

MediaPlayer.OnvideoSizeChangeListener: 视频宽高发生改变的时候会触发。当所设置的媒体资源没有视频图像、MediaPlayer没有设置展示的holder或者视频大小还没有测量出来的时候,获取宽高得到的都是0

MediaPlayer.OnErrorListerner: MediaPlayer出错时会触发,无论是播放过程中出错,还是准备过程中出错,都会触发。

6,MediaPlayer的状态图和生命周期

二、MP3音乐播放器

1,功能

从SD卡中读取MP3文件并加载到播放列表中,控制音乐的播放和停止,实现对播放列表中音乐的上一首、下一首的切换,播放完成时自动给跳转到下一首播放,当播放到最后一首音乐时自动切换到第一首进行播放。通过进度表跟踪播放进度和拖动进度条拖动进度。

2,代码

MainActivity.java文件:

package com.example.mp3;import android.Manifest;import android.app.Activity;import android.content.pm.PackageManager;import android.media.MediaPlayer;import android.os.Bundle;import android.os.Environment;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ListView;import android.widget.SeekBar;import android.widget.Toast;import androidx.core.app.ActivityCompat;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Timer;import java.util.TimerTask;public class MainActivity extends Activity {//默认继承AppCompatActivity,会报错private MediaPlayer player=new MediaPlayer();private List<String> musicList=new ArrayList<>();//保存SD卡中的所有音乐文件的名称private int currentListItem=0;//当前正在播放音乐的下表private boolean isPlaying;//表示当前是否正在播放音乐private SeekBar seekBar;private Timer timer;private TimerTask task;private int currentposition;//保存当前播放的音乐的位置@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);seekBar=findViewById(R.id.sb_seekbar);//动态申请权限final int permission= ActivityCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE);if(permission!= PackageManager.PERMISSION_GRANTED){//请求权限ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},10);}//获取sdcard/Music目录下所有的音乐文件并保存至musicList//获取这个目录下所有的文件// 得到sd卡内Music文件夹的路径String filePath = Environment.getExternalStorageDirectory().toString() + File.separator + "Music";// 得到该路径文件夹下所有的文件File fileAll = new File(filePath);File[] files = fileAll.listFiles();//判断files是否有音乐文件if(files!=null){//获得所有音乐文件的路径for(File f:files)musicList.add(f.getName());}//获得ListViewListView lv_list=findViewById(R.id.lv_list);//将musicList包装成ArrayAdapterArrayAdapter adapter=new ArrayAdapter<>(this,R.layout.array_item,musicList);//需要<String>,否则警告//为ListVeiw设置Adapterlv_list.setAdapter(adapter);//设置ListVIew的事件监听器lv_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {currentListItem=position;play();}});//通过保持在MusicLst中的路径找到音乐文件并播放File file = new File(filePath+"/"+musicList.get(currentListItem));//判断音频文件是否存在,//进行播放设置if(file.exists()){try{player.setDataSource(file.getAbsolutePath());player.prepare();player.start();followSeekBar();}catch(Exception e){Toast.makeText(MainActivity.this,"播放出dfdf错!",Toast.LENGTH_SHORT).show();}}else{//提示Toast.makeText(MainActivity.this,"音乐不存在!",Toast.LENGTH_SHORT).show();}//MedaiPlayer完成事件监听器,当前音乐播放完成后制动开始播放下一首player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {//当播放结束时取消计时timer.cancel();task.cancel();//播放下一首currentListItem=(currentListItem+1) % musicList.size();//播放到最后一首后,从头开始play();}});//上一首按钮的事件监听器Button bt_frontMusic=findViewById(R.id.bt_frontMusic);bt_frontMusic.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {frontMusic();//播放上一首}});//下一首按钮的事件监听器Button bt_nextMusic=findViewById(R.id.bt_nextMusic);bt_nextMusic.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {nextMusic();//播放下一首}});//播放暂停按钮的事件监听器Button bt_playPause=findViewById(R.id.bt_playPause);bt_playPause.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {playMusic();}});seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {currentposition=seekBar.getProgress();player.seekTo(currentposition);}});}//onCreateprivate void play(){try {player.reset();player.setDataSource(Environment.getExternalStorageDirectory().toString() + File.separator + "Music"+ File.separator+musicList.get(currentListItem));player.prepare();player.start();isPlaying=true;//正在播放标记置为truefollowSeekBar();}catch (Exception e){Toast.makeText(MainActivity.this,"播放出错!",Toast.LENGTH_SHORT).show();}}@Overrideprotected void onDestroy() {super.onDestroy();if(player.isPlaying()){player.stop();}player.release();}//播放上一首private void frontMusic(){if(currentListItem==0){Toast.makeText(MainActivity.this,"已经是第一首了!",Toast.LENGTH_LONG).show();}else{--currentListItem;play();}}//播放下一首private void nextMusic(){if(currentListItem+1==musicList.size()){Toast.makeText(MainActivity.this,"已经是最后一首了!",Toast.LENGTH_LONG).show();}else{++currentListItem;play();}}//播放暂停public void playMusic(){if(isPlaying){player.pause();isPlaying=false;}else{player.start();isPlaying=true;}}private void followSeekBar(){//获取当前歌曲的总时长int duration=player.getDuration();seekBar.setMax(duration);//计时器对象timer=new Timer();task=new TimerTask(){public void run(){//开启线程定时获取当前播放进度currentposition=player.getCurrentPosition();seekBar.setProgress(currentposition);}};timer.schedule(task,300,500);}}activity_main.xml文件:```xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><TextView android:id="@+id/tv_musicList"android:layout_width="match_parent"android:layout_height="20pt"android:text="歌曲列表"android:textSize="12pt"android:gravity="center_horizontal"/><ListViewandroid:id="@+id/lv_list"android:layout_width="match_parent"android:layout_height="560dp"android:divider="#666"android:dividerHeight="1dp"android:headerDividersEnabled="false" /><SeekBar android:id="@+id/sb_seekbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="100"android:progress="0"/></LinearLayout><LinearLayoutandroid:id="@+id/LL"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="bottom"android:orientation="horizontal"><Buttonandroid:id="@+id/bt_frontMusic"style="?android:attr/buttonBarButtonStyle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="上一首"android:textSize="10pt"android:layout_weight="1"/><Buttonandroid:id="@+id/bt_playPause"style="?android:attr/buttonBarButtonStyle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:text="播放/暂停"android:textSize="10pt" /><Buttonandroid:id="@+id/bt_nextMusic"style="?android:attr/buttonBarButtonStyle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:text="下一首"android:textSize="10pt" /></LinearLayout></LinearLayout>

array_item.xml文件:```xml<?xml version="1.0" encoding="utf-8"?><TextView android:id="@+id/TextView"xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="12pt"android:padding="5dp"android:shadowColor="#89a"android:shadowDx="4"android:shadowDy="4"android:shadowRadius="2"/>

因为需要读取SD卡,所以需要在AndroidManifest.xml中配置相应权限:

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

本代码还存在着较多bug,比如当SD卡没有音乐文件的时候会报错,所以需要进行完整的系统测试和bug修改,才能正常的时候。

在运行代码时,在如下代码中

//获取sdcard/Music目录下所有的音乐文件并保存至musicList//获取这个目录下所有的文件// 得到sd卡内Music文件夹的路径String filePath = Environment.getExternalStorageDirectory().toString() + File.separator + "Music";// 得到该路径文件夹下所有的文件File fileAll = new File(filePath);File[] files = fileAll.listFiles();

files对象一直为空,经过不断检查和debug依然没有发现代码存在的问题,最后无意间换上Genymotion的模拟器问题直接消失,最终确定应该是Android Studio自带的模拟器的问题。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。