這是一個亂七八糟的主界面
偷懶直接把所有操作都也在了MainActivity上面,主要是學習是怎麼運行的,之後滿滿完善吧。這裏的操作包括上下曲,播放暫停,隨機開關,列表跳轉播放。UI十分十分簡單。
public class MainActivity extends Activity implements OnClickListener {
private MediaPlayer mediaPlayer;
private MusicInfo musicInfo;
private Button mButton, mPre, mPlay, mNext, mRandom;
private SeekBar mSeekBar;
private boolean Random = false;
private TextView mName, mCurtime, mAllTime, mCount;
private int location = 0;
MusicAdapater adapater;
Cursor mCursor;
int musicCount;
int curplaytime;
String title;
int id;
private boolean isPause = true;
Handler handler = new Handler() {
};
Runnable runnable = new Runnable() {
@Override
public void run() {
if (mediaPlayer != null) {
title = musicInfo.getTitle();
mName.setText(title);
if (title != null) {
if (Random == false) {
mRandom.setText(getResources().getString(
R.string.randomon));
} else if (Random == true) {
mRandom.setText(getResources().getString(
R.string.randomoff));
}
int time = new Long(musicInfo.getTime()).intValue();
mAllTime.setText(MusicAdapater.Format(musicInfo.getTime()));
mSeekBar.setMax(time);
mSeekBar.setProgress(mediaPlayer.getCurrentPosition());
mCurtime.setText(MusicAdapater.Format(mediaPlayer
.getCurrentPosition()));
mCount.setText(musicInfo.getId() + "/" + musicCount);
}
}
handler.postDelayed(this, 1000);
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate()");
requestWindowFeature(Window.FEATURE_NO_TITLE);
initView();
musicCount = MusicList.getMusicInfos(this).size();
handler.postDelayed(runnable, 1000);
}
private void initView() {
setContentView(R.layout.main_activity);
mediaPlayer = new MediaPlayer(); //初始化MediaPlayer
musicInfo = new MusicInfo();
// 自動播放下一首
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
if (mediaPlayer != null) {
if (Random) { //因爲我定義的Random=false,即隨機關
location = location + 1;
songplay(location);
} else if (!Random) { //隨機開
location = getRandomNumber();
songplay(location);
}
}
}
});
mName = (TextView) findViewById(R.id.name);
mButton = (Button) findViewById(R.id.btn_list);
mPre = (Button) findViewById(R.id.pre);
mPlay = (Button) findViewById(R.id.play);
mNext = (Button) findViewById(R.id.next);
mRandom = (Button) findViewById(R.id.btn_random);
mSeekBar = (SeekBar) findViewById(R.id.time_seekbar);
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
mediaPlayer.getCurrentPosition();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
if (fromUser) { // 判斷是否爲用戶自己操作
mediaPlayer.seekTo(progress); // 設置音樂進度 就是拖動進度條也就是所謂的快進,後退
}
curplaytime = progress; //記錄當前播放時間
}
});
mCurtime = (TextView) findViewById(R.id.tv_curtime);
mAllTime = (TextView) findViewById(R.id.tv_alltime);
mCount = (TextView) findViewById(R.id.music_count);
mAllTime.setText("00:00");
mCurtime.setText("00:00");
mCount.setText("0/0");
mButton.setOnClickListener(this);
mNext.setOnClickListener(this);
mPre.setOnClickListener(this);
mPlay.setOnClickListener(this);
mRandom.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.btn_list:
Intent intent = new Intent(MainActivity.this, MusicList.class);
startActivityForResult(intent, 1); //因爲要從MusicList返回一個值,所以要用startActivityForResult
break;
case R.id.pre:
if (Random) {
if (location > 0 && location <= musicCount - 1) {
location = location - 1;
songplay(location);
} else if (location == 0) {
songplay(musicCount - 1);
location = musicCount - 1;
}
} else if (!Random) {
location = getRandomNumber();
songplay(location);
}
break;
case R.id.play:
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
} else {
if (curplaytime != 0) { //如果播放時間不爲0,就繼續上次時間播放
songplay(location);
mediaPlayer.seekTo(curplaytime);
} else {
songplay(location);
}
}
break;
case R.id.next:
nextsong();
break;
case R.id.btn_random:
if (Random == false) {
Random = true;
} else if (Random == true) {
Random = false;
}
default:
break;
}
}
private void nextsong() {
if (Random) {
if (location >= 0 && location < musicCount - 1) {
location = location + 1;
songplay(location);
} else {
songplay(0);
location = 0;
}
} else if (!Random) {
location = getRandomNumber();
songplay(location);
}
}
public void onDestroy() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
super.onDestroy();
}
public void songplay(int location) {
musicInfo = MusicList.getMusicInfos(getApplicationContext()).get(
location);
String url = musicInfo.getUrl();
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 返回值從[0,musicCount]
*
* @return location
*/
public int getRandomNumber() {
Random random = new Random();
int location = random.nextInt(musicCount);
return location;
}
//接收從listview傳過來的id,由於id索引從1開始,而location索引從0開始,所以要減1.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (1 == requestCode) {
if (1 == resultCode) {
Bundle bundle = data.getExtras();
id = bundle.getInt("id");
location = id - 1;
songplay(location);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
protected void onRestart() {
super.onRestart();
}
}
MusicInfo.java
public class MusicInfo {
private int id; // 歌曲ID
private String title; // 歌曲名稱
private String singer; // 歌手名稱
private long time;
private String url;
public MusicInfo(){}
public MusicInfo(int id, String title, String singer, long time, String url){
super();
this.id=id;
this.title = title;
this.singer = singer;
this.time = time;
this.url = url;
}
public String getUrl(){
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getId() {
return id;
}
public void setId(int ld){
this.id=ld;
}
public String getTitle(){
return title;
}
public void setTitle(String title){
this.title = title;
}
public String getSinger(){
return singer;
}
public void setSinger(String singer){
this.singer = singer;
}
public Long getTime(){
return time;
}
public void setTime(long time){
this.time = time;
}
}
一個不咋滴的適配器
public class MusicAdapater extends BaseAdapter {
private Context mContext;
private List<MusicInfo> musicInfos;
private MusicInfo musicInfo;
int mPosition;
public MusicAdapater(Context context,List<MusicInfo> musicInfos){
this.mContext = context;
this.musicInfos = musicInfos;
}
public int getPosition(){
return mPosition;
}
public void setPosition(int mPosition){
this.mPosition = mPosition;
}
@Override
public int getCount() {
// 決定listview有多少個item
return musicInfos.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view;
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.music_title, null);
holder.title = (TextView)convertView.findViewById(R.id.music_title);
holder.singer = (TextView)convertView.findViewById(R.id.music_singer);
holder.time = (TextView)convertView.findViewById(R.id.music_time);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
musicInfo =musicInfos.get(position);
holder.title.setText(musicInfo.getTitle());
holder.singer.setText(musicInfo.getSinger());
holder.time.setText(Format(musicInfo.getTime()));
return convertView;
}
class ViewHolder {
public TextView title; //音樂名
public TextView singer; // 歌手名
public TextView time; //時間
}
/**
* 時間轉化 把音樂時間的long型數據轉化爲“分:秒”
* @param time
* @return String hms
*/
public static String Format(long time) {
SimpleDateFormat format = new SimpleDateFormat("mm:ss");
String hms = format.format(time);
return hms;
}
}
音樂列表界面
public class MusicList extends Activity {
private ListView mListView;
MusicInfo musicInfo;
MusicAdapater adapater;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.music_list_activity);
initView(this);
}
void initView(Context context) {
mListView = (ListView) findViewById(R.id.listview);
mListView.setOnItemClickListener(new MusicItemCLickListener());
musicInfo = new MusicInfo();
adapater = new MusicAdapater(context, getMusicInfos(context));
mListView.setAdapter(adapater);
}
public static List<MusicInfo> getMusicInfos(Context context) {
Cursor mCursor = context.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
List<MusicInfo> musicInfos = new ArrayList<MusicInfo>();
for (int i = 0; i < mCursor.getCount(); i++) {
MusicInfo musicInfo = new MusicInfo();
mCursor.moveToNext();
int id = i + 1; //這是自定義音樂id,從1開始,方便之後使用,有規律
// long id = mCursor.getLong(mCursor.getColumnIndex(MediaStore.Audio.Media._ID)); // 音樂id,好像無規律
String title = mCursor.getString((mCursor.getColumnIndex(MediaStore.Audio.Media.TITLE)));// 音樂標題
String artist = mCursor.getString(mCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));// 藝術家
long duration = mCursor.getLong(mCursor.getColumnIndex(MediaStore.Audio.Media.DURATION));// 時長
int isMusic = mCursor.getInt(mCursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));// 是否爲音樂
String url = mCursor.getString(mCursor.getColumnIndex(MediaStore.Audio.Media.DATA)); //路徑
if (isMusic != 0) {
musicInfo.setId(id);
musicInfo.setTitle(title);
musicInfo.setSinger(artist);
musicInfo.setTime(duration);
musicInfo.setUrl(url);
musicInfos.add(musicInfo);
}
}
return musicInfos;
}
/*
* 這是listview item 的點擊事件 點擊後拋出音樂id給MainActivity,在MainActivity中根據id來播放相應的音樂
*/
private class MusicItemCLickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
if (getMusicInfos(getApplicationContext()) != null) {
MusicInfo musicInfo = getMusicInfos(getApplicationContext()).get(position);
int id2 = musicInfo.getId();
Intent intent = new Intent(MusicList.this, MainActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("id", id2);
intent.putExtras(bundle);
setResult(1, intent);
MusicList.this.finish();
}
}
}
}
因爲mediaplay是在MainActiviy中實例化的,爲了防止MainActiviy活動重複創建,修改 AndroidManifest 當然記得加權限##
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:launchMode="singleTask" //這個是防止重複創建棧頂活動的問題直接從返回棧中檢查是否存在該活動的實例,存在就直接使用,不存在就新建
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MusicList"></activity>
</application>
下面是佈局文件 main_activity.xml
佈局文件就沒什麼好說的了。隨便扔了幾個控件在上面
<?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" >
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="@android:color/black"
android:textSize="24sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<TextView
android:id="@+id/tv_curtime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="24sp" />
<SeekBar
android:id="@+id/time_seekbar"
android:layout_width="600dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:maxHeight="10dp"
android:minWidth="10dp" />
<TextView
android:id="@+id/tv_alltime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="24sp" />
</LinearLayout>
<TextView
android:id="@+id/music_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="@android:color/black"
android:textSize="24sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:gravity="center"
android:orientation="horizontal" >
<Button
android:id="@+id/btn_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/list"
android:textSize="32sp" />
<Button
android:id="@+id/pre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pre"
android:textSize="32sp" />
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/play"
android:textSize="32sp" />
<Button
android:id="@+id/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next"
android:textSize="32sp" />
<Button
android:id="@+id/btn_random"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/randomon"
android:textSize="32sp" />
</LinearLayout>
第二個佈局文件 music_list_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#000" >
</ListView>
第三個佈局文件music_title.xml
<?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" >
<TextView
android:id="@+id/music_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/music_singer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp" />
<TextView
android:id="@+id/music_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:layout_marginLeft="20dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp" >
</LinearLayout>
至於那些資源values就沒寫了
這是一個自動的跑馬燈自定義控件
有些字段太長了TextView大小又有限怎麼辦?那就讓它自己動起來。
創建一個類繼承自TextView
public class MarqueeTextView extends TextView
{
public MarqueeTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
// TODO Auto-generated method stub
if(focused) super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus)
{
// TODO Auto-generated method stub
if(hasWindowFocus) super.onWindowFocusChanged(hasWindowFocus);
}
@Override
public boolean isFocused()
{
return true;
}
}
然後是自定義控件的使用,記得給layout_width設定一個比較具體的大小,不然跑步起來哦
<com.android.auto.autohome.MarqueeTextView
android:id="@+id/music_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:ellipsize="marquee"
android:singleLine="true"
android:text="@string/unknow"
android:textColor="@color/white"
android:textSize="20sp" />