android简易播放器<2>:activity和service同步显示

程序的结构:Activity+Service,前者负责界面交,后者负责对音乐文件的各种操作,它们之间通过broadcast和broadcastReceive来进行通讯。
     1.读取歌词文件,放入到一个ArrayList里,生成adapter,给listView注入数据。
            2.点击按钮或移动seekbar滑块后,通过broadcast给service发送信息,service收到信息,对音乐文件进行操作。
            3.启动一个线程,向service发送broadcast来询问歌曲的播放状态和播放得进度,receiver接收返回的broadcast来刷新listview ,seekbar,现在播放到的时间等控件的显示值。
相应的代码:
View Code
package com.andy.media;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.util.EncodingUtils;



import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class AndyMediaPlayer extends Activity implements OnClickListener {
private ImageButton back;
private ImageButton forward;
private ImageButton previous;
private ImageButton next;
private ImageButton play;
private ImageButton finish;
private SeekBar seekBar;
private ListView listview;
private TextView status;
private TextView currentTime;
private TextView totalTime;

private boolean isPlaying = false;

private ArrayList fileList = new ArrayList();
private int currentIndex;
private boolean loop;

private int fileId;
private String singer;
private String album;
private ArrayList timeList = new ArrayList();
private ArrayList<HashMap> lrcContent = new ArrayList<HashMap>();
private int currentRow;
private int totalTimeData;
BroadcastReceiver recevier;
@Override
protected void onDestroy() {
// TODO Auto-generated method stub

super.onDestroy();
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initUI();

recevier = new BroadcastReceiver(){

@Override
public void onReceive(Context context, Intent intent) {
Bundle bd = intent.getBundleExtra("refresh");
if(bd != null){
int p = bd.getInt("progress");
seekBar.setProgress(p);
int mms = bd.getInt("mms");
int total = bd.getInt("total");
int m = (int)mms/(1000*60);
int s =( mms-m*1000*60)/1000;
String mm = m+":"+s;
Log.i("recvF",mm);
currentTime.setText(mm);

int status1 = bd.getInt("status");
if(status1==1){
status.setText(AndyMediaPlayer.this.getResources().getString(R.string.playing));
}else{
status.setText(AndyMediaPlayer.this.getResources().getString(R.string.pausePlaying));
}

currentRow=0;
String ts = (String) lrcContent.get(currentRow).get("time");
int tsint = Integer.parseInt(ts);
while(tsint<mms){
if(currentRow>=lrcContent.size()-1) break;
ts = (String) lrcContent.get(currentRow+1).get("time");
tsint = Integer.parseInt(ts);
if(tsint<mms){
currentRow++;
}
}
Log.i("cccur",currentRow+"");
System.out.println(listview.getChildCount());
int row = currentRow % listview.getChildCount();
listview.setSelection(currentRow);
// if(row<listview.getChildCount()){
// LinearLayout v=null;
// if(row-1>=0){
// v = (LinearLayout)listview.getChildAt(row-1);
// System.out.println(v.getChildAt(0).getClass());
// ((TextView)(v.getChildAt(0))).setTextColor(Color.WHITE);
// }
//
// v = (LinearLayout)listview.getChildAt(row);
// System.out.println(v.getChildAt(0).getClass());
// ((TextView)(v.getChildAt(0))).setTextColor(Color.RED);
// //v.setBackgroundColor(R.color.blue);
// v.setFocusable(true);
// v.setSelected(true);
// listview.setSelection(currentRow);
// }
//listview.getAdapter().getView(currentIndex, null, listview).setBackgroundColor(R.color.blue);
totalTimeData = total;
m = (int)total/(1000*60);
s =( total-m*1000*60)/1000;
mm = m+":"+s;
totalTime.setText(mm);
}


}

};

IntentFilter filter = new IntentFilter();
filter.addAction("com.andy.fromService");
this.registerReceiver(recevier, filter);

startService();

new Thread(){
public void run(){
while(true){
Intent intent = new Intent("com.andy.toService");
Bundle bd = new Bundle();
bd.putInt("command", 10);
intent.putExtra("info", bd);
sendBroadcast(intent);

try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
}.start();

initFile();

SimpleAdapter adapter = new SimpleAdapter(this, (List<? extends Map<String, ?>>) lrcContent, R.layout.lrclist,
new String[]{"content"}, new int[]{R.id.lrccontent});
listview.setAdapter(adapter);
}

public void startService(){
Intent intent = new Intent(this,AudioPlayerService.class);
Bundle bundel = new Bundle();
//if(!fileList.isEmpty()&&currentIndex<fileList.size())
{
//bundel.putString("file", (String) fileList.get(currentIndex));
bundel.putInt("command", 0);
bundel.putBoolean("loop", loop);
}
intent.putExtra("info", bundel);
this.startService(intent);

}



public void initUI(){
back = (ImageButton)findViewById(R.id.back);
forward = (ImageButton)findViewById(R.id.forward);
previous = (ImageButton)findViewById(R.id.previous);
next = (ImageButton)findViewById(R.id.next);
play = (ImageButton)findViewById(R.id.play);
finish = (ImageButton)findViewById(R.id.backTbegin);
currentTime = (TextView)findViewById(R.id.currentTime);
totalTime = (TextView)findViewById(R.id.totalTime);

back.setOnClickListener(this);
forward.setOnClickListener(this);
previous.setOnClickListener(this);
next.setOnClickListener(this);
play.setOnClickListener(this);
finish.setOnClickListener(this);

seekBar = (SeekBar)findViewById(R.id.seekBar);
seekBar.setMax(100);
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(fromUser)
changePlayerProgress(progress);

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

});
status = (TextView)findViewById(R.id.status);
listview = (ListView)findViewById(R.id.irclist);
listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}

@Override
public void onClick(View v) {
int id = v.getId();
switch(id){
case R.id.back:
case R.id.forward:
case R.id.backTbegin:
changeProgress(id);
break;
case R.id.previous:
case R.id.next:
changeMusic(id);
break;
case R.id.play:
changeStatus();
break;
default: break;
}
}

private void changeStatus() {
Intent intent = new Intent("com.andy.toService");
Bundle bd = new Bundle();
bd.putInt("command", isPlaying?1:0);
intent.putExtra("info", bd);
isPlaying = !isPlaying;
this.sendBroadcast(intent);

}

private void changeMusic(int id) {
// TODO Auto-generated method stub

}

private void changePlayerProgress(int progress){
Intent intent = new Intent("com.andy.toService");
Bundle bd = new Bundle();
bd.putInt("command", 6);
bd.putInt("progress", progress);
intent.putExtra("info", bd);
this.sendBroadcast(intent);
}

private void changeProgress(int id) {
if(id == R.id.forward){
sendChangeProgressIntent(9);
}else if(id == R.id.back){
sendChangeProgressIntent(8);
}else if(id == R.id.backTbegin){
sendChangeProgressIntent(7);
}

}

private void sendChangeProgressIntent(int towards){
Intent intent = new Intent("com.andy.toService");
Bundle bd = new Bundle();
bd.putInt("command", towards);
intent.putExtra("info", bd);
this.sendBroadcast(intent);
}

private void initFile(){
fileId = R.raw.love_lrc;
InputStream in = this.getResources().openRawResource(R.raw.love_lrc);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(in,"GB2312"));
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String s = "";
try{
if(reader==null) return ;
while((s=reader.readLine())!=null){

int index =0;
int index2 = 0;
index2= s.indexOf("]");
if((index = s.indexOf("[ar:"))!=-1){
singer = s.substring(index+4,index2);
}else if((index = s.indexOf("[ti:"))!=-1){
album = s.substring(index+4,index2);
}else if(!s.endsWith("]")){
index = s.indexOf("[");
index2 = s.indexOf("]");
String time = s.substring(index+1,index2);
String cc = s.substring(index2+1);
index = time.indexOf(":");
index2 = time.indexOf(".");

Log.i("time",time.substring(0, index));
Log.i("time",time.substring(index+1, index2));
Log.i("time",time.substring(index2+1));
int mms = Integer.parseInt(time.substring(0, index))*60*1000+
Integer.parseInt(time.substring(index+1, index2))*1000+
Integer.parseInt(time.substring(index2+1))*10;

HashMap<String, String> map = new HashMap();
map.put("time", mms+"");
cc = EncodingUtils.getString(cc.getBytes(), "UTF-8");
map.put("content", cc);
Log.i("irc",cc);
lrcContent.add(map);
}
}
reader.close();
}catch(Exception e){
e.printStackTrace();
}
}




}
service代码:
 
View Code
package com.andy.media;

import android.app.Service;
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.IBinder;
import android.util.Log;

public class AudioPlayerService extends Service {
public static final int COMMAND_TO_PLAY = 0;
public static final int COMMAND_TO_PAUSE = 1;
public static final int COMMAND_TO_FINISH = 2;
private static final int COMMAND_TO_RESTART = 3;
private final String TAG = "tag";

MediaPlayer mp;

boolean loop;

BroadcastReceiver recevier = new BroadcastReceiver(){

@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getBundleExtra("info");
int command = bundle.getInt("command");
switch(command){
case 9:
AudioPlayerService.this.changeProgress(true);
break;
case 8:
AudioPlayerService.this.changeProgress(false);
break;
case 7:
AudioPlayerService.this.restartPlay();
break;
case 6:
int p = bundle.getInt("progress");
AudioPlayerService.this.changeProgressData(p);
break;
case 1:
case 0:
changeMediaStatus(command);
break;
case 10:
int progress = (int)100*mp.getCurrentPosition()/mp.getDuration();
int mms = mp.getCurrentPosition();
int total = mp.getDuration();
Bundle bd = new Bundle();
bd.putInt("progress", progress);
bd.putInt("mms", mms);
bd.putInt("total", total);
bd.putInt("status", mp.isPlaying()?1:0);
Intent i = new Intent("com.andy.fromService");
i.putExtra("refresh", bd);
Log.i("sendF","send fresh");
sendBroadcast(i);
break;
}

}

};


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

@Override
public void onCreate() {
Log.i(TAG,"service on create");
IntentFilter filter = new IntentFilter();
filter.addAction("com.andy.toService");
this.registerReceiver(recevier, filter);
super.onCreate();
}

@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}

@Override
public void onStart(Intent intent, int startId) {
Log.i(TAG,"service on start");
Bundle bl = intent.getBundleExtra("info");
int command = bl.getInt("command");
loop = bl.getBoolean("loop");
changeMediaStatus(command);
super.onStart(intent, startId);
}

private void changeMediaStatus(int command) {
if(mp == null){
mp = MediaPlayer.create(this, R.raw.love);
}
switch(command){
case COMMAND_TO_PLAY:
mp.start();
break;
case COMMAND_TO_PAUSE:
if(mp.isPlaying())
mp.pause();
break;
case COMMAND_TO_FINISH:
mp.stop();
case COMMAND_TO_RESTART:

break;
default :break;
}
}


public void changeProgress(boolean isForward){
if(isForward){
mp.seekTo(mp.getCurrentPosition()+5000<mp.getDuration()?
mp.getCurrentPosition()+5000:mp.getDuration());
}else{
mp.seekTo(mp.getCurrentPosition()-5000>0?
mp.getCurrentPosition():0);
}
}

public void changeProgressData(int p){
int len = mp.getDuration()*p/100;
mp.seekTo(len);
}

public void restartPlay(){
mp.seekTo(0);
}

public int getProgress(){
return (int)(100*mp.getCurrentPosition()/mp.getDuration());
}

public void changeProgress(int progress){
if(progress<0)progress = 0;
else if(progress>100) progress=100;
int len =(int) mp.getDuration()*progress/100;
mp.seekTo(len);
}


}
遇到的问题:
 (1)歌词乱码的问题:获取文件的输入流时,指定源文件的编码方式,然后在转化成项目中的编码方式。
 (2)MediaPlayer 播放的步骤:可以参考http://developer.android.com/reference/android/media/MediaPlayer.html状态图。
    mp = MediaPlayer.create(this, R.raw.love);之后已经处于prepared状态,可以自己start()来播放,可以看create()的源码:
  
View Code
 public static MediaPlayer create(Context context, int resid) {
try {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
if (afd == null) return null;

MediaPlayer mp = new MediaPlayer();
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
mp.prepare();
return mp;
} catch (IOException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (IllegalArgumentException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (SecurityException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
}
return null;
}
  (3)seekbar的监听器接口OnSeekBarChangeListener里的一个方法public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) 
的fromUser的含义是:进度的change事件是否是由用户的操作而改变的。
posted @ 2011-10-15 19:17  AndyLau2  阅读(765)  评论(0编辑  收藏  举报