对于音乐播放器来说,可以体现很多种android开发所要运用的技术,比方说数据库的查询,自定义控件的开发,事件的处理,Activity的运用,service的开发,多媒体的运用,布局的运用,BaseAdapter的开发,网络应用等,是非常适合用来做为考察自己android学习的项目
一.自定义控件
android中的按钮并没有直接提供播放的三角式按钮,所以这里需要我们自己实现这部分按钮,要实现的按钮有播放/暂停,模式切换,前进,后退,即点击播放后会变成暂停键,模式切换可以从单曲循环,顺序播放,循环播放,随机播放的按钮中互相变化,具体实现过程如下,首先定义一个attrs.xml文件,在res/values文件夹下,定义各个按键的键值,之后会在自定义控件中使用
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomAudioPlayButton">
<attr name="ButtonValue">
<enum name="start" value="0"/>
<enum name="forward" value="1"/>
<enum name="backward" value="2"/>
<enum name="query" value="3"/>
<enum name="playmode" value="4"/>
</attr>
</declare-styleable>
</resources>
之后就需要在入口文件处注册这个数值,注册方法如下,在要使用自定义组件的xml文件中写入xmlns:custom=”http://schemas.android.com/apk/res/com.example.mp3site”其中com.example.mp3site为所处包名,xmlns:custom中的custom为自定义,代表使用数据时的关键字
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.example.mp3site"
接下来就是控件的实现了,可以继承VIew类来重载其中的方法进行自己绘制需要的控件,对于播放按钮来说有两种选择,一是在中间载入图片,另一种就是通过drawline自己绘制,这里采用后者进行描述,通过typedarray来获取自定义控件使用时所输入的数据,因为是按钮所以还需要设置clickable,而自定义控件并没有写好的点击事件,那么使用使用可以通过ontouch来实现,也就是触摸,所以还需要设置触摸事件,完整的过程如下
public playbutton(Context context, AttributeSet attrs) {
super(context, attrs);
//获取所定义的值
TypedArray typeArray=context.obtainStyledAttributes(attrs,R.styleable.CustomAudioPlayButton);
type=typeArray.getInt(R.styleable.CustomAudioPlayButton_ButtonValue, defaultType);
Log.i("player","start draw"+type);
typeArray.recycle();
InitView();
//设置为可点击
this.setClickable(true);
//设置触摸事件
this.setOnTouchListener(new onTouch());
// TODO Auto-generated constructor stub
}
之后就是绘制按钮的图像了了,这里以播放和暂停来作为例子,首先我们需要一个外框图案,这里选择使用方形来作为外框,之后就是播放和暂停的切换,所以需要一个代表播放还是暂定的标志位,所以绘制的方法如下:
public void drawstartButton(Canvas canvas,Boolean pressed){
//如果是true,画双竖线,false话右三角
float []point={(float) (0.3*width),(float)0.1*height,(float)0.9*height,(float) (0.6*width),(float) (0.5*height)};
Log.i("player","start draw start");
if(flag_startstop){
canvas.drawLine(point[0], point[1],point[0],point[2], pressedpaint);
canvas.drawLine(point[3], point[1],point[3],point[2], pressedpaint);
}else{
canvas.drawLine(point[0], point[1],point[0],point[2], unpresspaint);
canvas.drawLine(point[0], point[1],point[3],point[4], unpresspaint);
canvas.drawLine(point[0], point[2],point[3],point[4], unpresspaint);
}
}
画完按钮之后还需要对触摸事件的响应,在触摸后切换图像的标志位,来达到播放和暂停的互相切换的目的
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
pressed = true;
if(type==start){
if(flag_startstop){
flag_startstop=false;
}else{
flag_startstop=true;
}}else if(type==mode){
if(playmode<4){
playmode++;
}else{
playmode=1;
}
}
//刷新视图
invalidate();
break;
case MotionEvent.ACTION_UP:
pressed = false;
invalidate();
break;
}
return false;
}
接下来就是使用了,使用方法如下,包名后写上类名,custom:ButtoValue即为所传的值
<com.example.mp3site.playbutton
android:id="@+id/btnStart"
android:layout_width="40dp"
android:layout_height="64dp"
android:layout_marginRight="25dp"
android:layout_toRightOf="@+id/btnMode"
custom:ButtonValue="start" />
按钮实例图,很丑=。=
二.mediaplayer的使用
mediaplayer.stop()//停止播放
mediaplayer.pause()//暂停播放
mediaplayer.start()//开始播放
mediaplayer.prepare()//准备播放
这些就是基本使用方法,值得注意的是,在首次播放时,需要等待prepare结束,在调用start进行播放
播放函数如下:
public void playmedia(String Name){
TextView tv=(TextView)MainActivity.this.findViewById(R.id.MusicName);
tv.setText(Name);
mPlay=new MediaPlayer();
//将进度条置为0
mPbar.setProgress(0);
//如果在播放,就重置播放器
if(mPlay.isPlaying()){
mPlay.reset();
}
try{
//设置播放文件流
String datapath="/sdcard/"+Name+".mp3";
mPlay.setDataSource(datapath);
//缓冲
mPlay.setOnPreparedListener(new OnPreparedListener(){
@Override
public void onPrepared(MediaPlayer mPlay) {
// TODO Auto-generated method stub
//获取Mp3文件长度
int width=mPlay.getDuration();
mPbar.setMax(width/1000);
//开始播放
mPlay.start();
//单进程可能会阻塞
new Thread(new refresh(width,mPlay)).start();
}
});
mPlay.prepareAsync();
}
三,通过系统提供的considerprovider来查询音乐的具体信息,因为是系统自带的,所以和自定义provider不同并不需要注册,直接拿来用就行了,具体使用的过程之前的笔记已经有了,就不再赘述了,下面就是调用过程MediaStore是系统自带的,非自己定义。
String [] mediaculm={