編輯:關於Android編程
[java]
業務:android的程序,實現播放音樂的功能。
知識點:
1.使用了android的四大組件中的三個(Activity,Service,Broadcast)
activity與serivice之間的通信用廣播Broadcast組件實現,程序中有10多個廣播的發布和接收。
2.還使用了線程和Application類來保存全局性的數據。
在Service中啟動一個線程是為了在activity需要的時候,不間斷地給activity發布更新進度的廣播,activity收到後再界面上展示出來。
難點:
個人感覺廣播雖然多,但是邏輯上一般,不是很復雜,稍微比較難理解的是線程的啟動和停止條件的判段和service中Destroy方法中的收尾清理工作。
1.在這幾種條件下需要喚醒線程。
1)play()方法中,當開始播放音樂的時候,讓它就開始干活。
2)seekto()方法中,當拖動seekBar需要重新定位並且播放音樂的時候,讓它就開始干活。
3)當activity發布廣播,請求service發布一個更新進度的廣播的時候需要喚醒線程,讓它就開始干活。
4)Service方法要退出銷毀的時候需要喚醒線程,讓其退出循環。
完整項目代碼:
部分代碼:
主Activity的全部代碼
[java] package com.tarena.day1901;
import com.tarena.entity.Music;
import com.tarena.utils.Consts;
import com.tarena.utils.FormatUtils;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class MainActivity extends Activity {
private ListView lvMusics;
private MenuInflater inflater;
private MusicAdapter adapter;
private Button btnPlayOrPause;
private MusicApplication app;
private TextView tvMusicName;
private TextView tvDuration;
private InnerBroadcastReceiver receiver;
private SeekBar sbProgress;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
inflater=getMenuInflater();
app=(MusicApplication)getApplication();
//設置界面
setupView();
addlistener();
//啟動service
Intent intent=new Intent(this, MusicService.class);
startService(intent);
//創建一個廣播接收器
createReceiver();
}
//activity啟動,發送廣播給service告知需要發送進度更新的廣播
@Override
protected void onStart() {
super.onStart();
Intent intent=new Intent(Consts.ACTION_NEED_UPDATE_PROGRESS);
intent.putExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, true);
sendBroadcast(intent);
Log.i("info", "onStart");
}
@Override
protected void onResume() {
Log.i("info", "onREsume");
super.onResume();
}
//activity停止,發送廣播給service告知可以停止發送進度更新的廣播
@Override
protected void onStop() {
super.onStop();
Intent intent=new Intent(Consts.ACTION_NEED_UPDATE_PROGRESS);
intent.putExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, false);
sendBroadcast(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);//MainActivity銷毀的時候,對廣播接收器,解除注冊
}
//設置界面
public void setupView(){
lvMusics=(ListView)findViewById(R.id.lvMusics);
adapter=new MusicAdapter(this);
lvMusics.setAdapter(adapter);
btnPlayOrPause=(Button)findViewById(R.id.btnPlayOrPause);
tvMusicName=(TextView)findViewById(R.id.tvMusicName);
tvDuration=(TextView)findViewById(R.id.tvDuration);
sbProgress=(SeekBar)findViewById(R.id.sbProgress);
}
//添加菜單
@Override
public boolean onCreateOptionsMenu(Menu menu) {
inflater.inflate(R.menu.opts,menu);
return super.onCreateOptionsMenu(menu);
}
//選擇系統菜單選項,發送廣播
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent=null;
switch (item.getItemId()) {
case R.id.menu_sub_loop:
intent=new Intent(Consts.ACTION_PLAY_MODE);
intent.putExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_LOOP);
sendBroadcast(intent);
Log.i("info", "循環");
break;
case R.id.menu_sub_random:
intent=new Intent(Consts.ACTION_PLAY_MODE);
intent.putExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_RADOM);
sendBroadcast(intent);
Log.i("info", "隨機");
break;
case R.id.menu_opts_exit:
intent=new Intent(Consts.ACTION_APP_STOPED);
sendBroadcast(intent);
finish();
break;
}
return super.onOptionsItemSelected(item);
}
//監聽用戶拖動seekbar,並記錄拖動的位置
private void addlistener() {
sbProgress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(fromUser){
Intent intent=new Intent(Consts.ACTION_SEEK_TO);
intent.putExtra(Consts.EXTRA_SEEK_TO, progress);
sendBroadcast(intent);
}
}
});
}
//用戶不同的操作,執行相應的操作
public void doClick(View v){
Intent intent=null;
switch (v.getId()) {
case R.id.btnNext:
intent=new Intent(Consts.ACTION_PLAY_NEXT);
btnPlayOrPause.setText("暫停");
break;
case R.id.btnPlayOrPause:
String text=((Button)v).getText().toString();
if("播放".equals(text)){
intent=new Intent(Consts.ACTION_PLAY);
((Button)v).setText("暫停");
}else if("暫停".equals(text)){
intent=new Intent(Consts.ACTION_PAUSE);
((Button)v).setText("播放");
}
break;
case R.id.btnPrevious:
intent=new Intent(Consts.ACTION_PLAY_PREVIOUS);
btnPlayOrPause.setText("暫停");
break;
}
sendBroadcast(intent);
}
//創建一個廣播接收器
private void createReceiver() {
receiver=new InnerBroadcastReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction(Consts.ACTION_CURRENT_MUSIC_CHANGE);
filter.addAction(Consts.ACTION_START_UPDATE_PROGRESS);
filter.addAction(Consts.ACTION_SEND_PLAYING_STATE);
registerReceiver(receiver, filter);
}
private class InnerBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
//接收廣播,音樂變更,前端展示更新為新的音樂的名字和時長
if(Consts.ACTION_CURRENT_MUSIC_CHANGE.equals(action)){
Music music=app.getCurrentMusic();
tvMusicName.setText(music.getName());
tvDuration.setText(FormatUtils.format(music.getDuration()));
}else if(Consts.ACTION_START_UPDATE_PROGRESS.equals(action)){
//當前播放時長
int progress=intent.getIntExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, 0);
//總時長
int Duration = (int)app.getCurrentMusic().getDuration();
tvDuration.setText(FormatUtils.format(progress));//在界面顯示歌曲已播放時長
sbProgress.setProgress(progress*100/Duration);
}else if(Consts.ACTION_SEND_PLAYING_STATE.equals(action)){
int state=intent.getIntExtra(Consts.EXTRA_PLAY_STATE, Consts.STATE_OTHERS);
Music m=app.getCurrentMusic();
int progress=intent.getIntExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, 0);
int Duration = (int)app.getCurrentMusic().getDuration();
tvDuration.setText(FormatUtils.format(progress));//在界面顯示歌曲已播放時長
sbProgress.setProgress(progress*100/Duration);
tvMusicName.setText(m.getName());
if(state==Consts.STATE_PAUSE){
btnPlayOrPause.setText("播放");
}else if(state==Consts.STATE_ISPLAYING){
btnPlayOrPause.setText("暫停");
}
}
}
}
}
package com.tarena.day1901;
import com.tarena.entity.Music;
import com.tarena.utils.Consts;
import com.tarena.utils.FormatUtils;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class MainActivity extends Activity {
private ListView lvMusics;
private MenuInflater inflater;
private MusicAdapter adapter;
private Button btnPlayOrPause;
private MusicApplication app;
private TextView tvMusicName;
private TextView tvDuration;
private InnerBroadcastReceiver receiver;
private SeekBar sbProgress;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
inflater=getMenuInflater();
app=(MusicApplication)getApplication();
//設置界面
setupView();
addlistener();
//啟動service
Intent intent=new Intent(this, MusicService.class);
startService(intent);
//創建一個廣播接收器
createReceiver();
}
//activity啟動,發送廣播給service告知需要發送進度更新的廣播
@Override
protected void onStart() {
super.onStart();
Intent intent=new Intent(Consts.ACTION_NEED_UPDATE_PROGRESS);
intent.putExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, true);
sendBroadcast(intent);
Log.i("info", "onStart");
}
@Override
protected void onResume() {
Log.i("info", "onREsume");
super.onResume();
}
//activity停止,發送廣播給service告知可以停止發送進度更新的廣播
@Override
protected void onStop() {
super.onStop();
Intent intent=new Intent(Consts.ACTION_NEED_UPDATE_PROGRESS);
intent.putExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, false);
sendBroadcast(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);//MainActivity銷毀的時候,對廣播接收器,解除注冊
}
//設置界面
public void setupView(){
lvMusics=(ListView)findViewById(R.id.lvMusics);
adapter=new MusicAdapter(this);
lvMusics.setAdapter(adapter);
btnPlayOrPause=(Button)findViewById(R.id.btnPlayOrPause);
tvMusicName=(TextView)findViewById(R.id.tvMusicName);
tvDuration=(TextView)findViewById(R.id.tvDuration);
sbProgress=(SeekBar)findViewById(R.id.sbProgress);
}
//添加菜單
@Override
public boolean onCreateOptionsMenu(Menu menu) {
inflater.inflate(R.menu.opts,menu);
return super.onCreateOptionsMenu(menu);
}
//選擇系統菜單選項,發送廣播
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent=null;
switch (item.getItemId()) {
case R.id.menu_sub_loop:
intent=new Intent(Consts.ACTION_PLAY_MODE);
intent.putExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_LOOP);
sendBroadcast(intent);
Log.i("info", "循環");
break;
case R.id.menu_sub_random:
intent=new Intent(Consts.ACTION_PLAY_MODE);
intent.putExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_RADOM);
sendBroadcast(intent);
Log.i("info", "隨機");
break;
case R.id.menu_opts_exit:
intent=new Intent(Consts.ACTION_APP_STOPED);
sendBroadcast(intent);
finish();
break;
}
return super.onOptionsItemSelected(item);
}
//監聽用戶拖動seekbar,並記錄拖動的位置
private void addlistener() {
sbProgress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(fromUser){
Intent intent=new Intent(Consts.ACTION_SEEK_TO);
intent.putExtra(Consts.EXTRA_SEEK_TO, progress);
sendBroadcast(intent);
}
}
});
}
//用戶不同的操作,執行相應的操作
public void doClick(View v){
Intent intent=null;
switch (v.getId()) {
case R.id.btnNext:
intent=new Intent(Consts.ACTION_PLAY_NEXT);
btnPlayOrPause.setText("暫停");
break;
case R.id.btnPlayOrPause:
String text=((Button)v).getText().toString();
if("播放".equals(text)){
intent=new Intent(Consts.ACTION_PLAY);
((Button)v).setText("暫停");
}else if("暫停".equals(text)){
intent=new Intent(Consts.ACTION_PAUSE);
((Button)v).setText("播放");
}
break;
case R.id.btnPrevious:
intent=new Intent(Consts.ACTION_PLAY_PREVIOUS);
btnPlayOrPause.setText("暫停");
break;
}
sendBroadcast(intent);
}
//創建一個廣播接收器
private void createReceiver() {
receiver=new InnerBroadcastReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction(Consts.ACTION_CURRENT_MUSIC_CHANGE);
filter.addAction(Consts.ACTION_START_UPDATE_PROGRESS);
filter.addAction(Consts.ACTION_SEND_PLAYING_STATE);
registerReceiver(receiver, filter);
}
private class InnerBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
//接收廣播,音樂變更,前端展示更新為新的音樂的名字和時長
if(Consts.ACTION_CURRENT_MUSIC_CHANGE.equals(action)){
Music music=app.getCurrentMusic();
tvMusicName.setText(music.getName());
tvDuration.setText(FormatUtils.format(music.getDuration()));
}else if(Consts.ACTION_START_UPDATE_PROGRESS.equals(action)){
//當前播放時長
int progress=intent.getIntExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, 0);
//總時長
int Duration = (int)app.getCurrentMusic().getDuration();
tvDuration.setText(FormatUtils.format(progress));//在界面顯示歌曲已播放時長
sbProgress.setProgress(progress*100/Duration);
}else if(Consts.ACTION_SEND_PLAYING_STATE.equals(action)){
int state=intent.getIntExtra(Consts.EXTRA_PLAY_STATE, Consts.STATE_OTHERS);
Music m=app.getCurrentMusic();
int progress=intent.getIntExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, 0);
int Duration = (int)app.getCurrentMusic().getDuration();
tvDuration.setText(FormatUtils.format(progress));//在界面顯示歌曲已播放時長
sbProgress.setProgress(progress*100/Duration);
tvMusicName.setText(m.getName());
if(state==Consts.STATE_PAUSE){
btnPlayOrPause.setText("播放");
}else if(state==Consts.STATE_ISPLAYING){
btnPlayOrPause.setText("暫停");
}
}
}
}
}
MusicService的完整代碼
[java] view plaincopyprint?package com.tarena.day1901;
import java.io.IOException;
import java.util.Random;
import com.tarena.entity.Music;
import com.tarena.utils.Consts;
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.media.MediaPlayer.OnCompletionListener;
import android.os.IBinder;
import android.util.Log;
public class MusicService extends Service {
private MediaPlayer player;
private MusicApplication app;
private boolean isPause;
private boolean needUpdate; //需要發布更新進度
private boolean isLoop;//控制循環語句
private int playMode;
private Random random;
private InnerBroadcastReceiver receiver;
private Thread workThread;
@Override
public void onCreate() {
super.onCreate();
app=(MusicApplication)getApplication();
player=new MediaPlayer();
playMode=Consts.PLAY_MODE_LOOP;
isLoop=true;
needUpdate=true;
random=new Random();
//設置自動播放下一首的監聽器
addlistener();
//添加接收器
createReceiver();
workThread=new Thread(){
public void run() {
while(isLoop){
while(isLoop&&needUpdate&&player.isPlaying()){
Intent intent=new Intent(Consts.ACTION_START_UPDATE_PROGRESS);
//將當前播放的音樂播放的時間抽的位置包裝傳遞
intent.putExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, player.getCurrentPosition());
sendBroadcast(intent);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//此工作線程需要不停地循環工作,除非修改循環標志。不需要發送廣播的時候就等待,睡大覺
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
};
workThread.start();
}
//service銷毀的時候,解除注冊廣播接收器
@Override
public void onDestroy() {
unregisterReceiver(receiver);
//喚醒線程,讓線程退出循環
isLoop = false;
synchronized (workThread) {
workThread.notify();
}
//如果音樂還在播放,停止其播放
if (player.isPlaying())
player.stop();
//釋放資源
player.release();
super.onDestroy();
}
//如果是isPause狀態值為true,直接播放,else重置player,最後要記得喚醒線程
public void play(){
if(isPause){
player.start();
}else{
Music music=app.getCurrentMusic();
String path=music.getMusicPath();
if(path!=null){
try {
player.reset();
player.setDataSource(path);
player.prepare();
player.start();
//當前索引所表示的歌曲變化,發布廣播
Intent intent=new Intent(Consts.ACTION_CURRENT_MUSIC_CHANGE);
sendBroadcast(intent);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
isPause=false;//音樂開始播放,將暫停狀態標志置為false
synchronized (workThread) {
workThread.notify();
}
}
//如果正在播放,暫停播放
public void pause(){
if(player.isPlaying()){
player.pause();
isPause=true;
}
}
//開始播放後一首
public void next(){
int index=app.getCurrentPosition();
switch (playMode) {
case Consts.PLAY_MODE_LOOP:
if(++index>=app.getPlayListSize()){
index=0;
}
break;
case Consts.PLAY_MODE_RADOM:
do {
index=random.nextInt(app.getPlayListSize());
} while (index==app.getCurrentPosition());
break;
}
app.setCurrentPosition(index);
isPause=false;
play();
}
//開始播放前一首
public void previous(){
int index=app.getCurrentPosition();
switch (playMode) {
case Consts.PLAY_MODE_LOOP:
if(--index<=0){
index=app.getPlayListSize()-1;
}
break;
case Consts.PLAY_MODE_RADOM:
do {
index=random.nextInt(app.getPlayListSize());
} while (index==app.getCurrentPosition());
break;
}
app.setCurrentPosition(index);
isPause=false;
play();
}
//定位到指定的時間值開始播放
public void seekTo(int positon){
player.seekTo(positon);
player.start();
synchronized (workThread) {
workThread.notify();
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
//設置自動播放下一首
public void addlistener(){
player.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
next();
}
});
}
//添加接收器
private void createReceiver() {
receiver=new InnerBroadcastReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction(Consts.ACTION_PAUSE);
filter.addAction(Consts.ACTION_PLAY);
filter.addAction(Consts.ACTION_PLAY_NEXT);
filter.addAction(Consts.ACTION_PLAY_PREVIOUS);
filter.addAction(Consts.ACTION_PLAY_MODE);
filter.addAction(Consts.ACTION_APP_STOPED);
filter.addAction(Consts.ACTION_NEED_UPDATE_PROGRESS);
filter.addAction(Consts.ACTION_SEEK_TO);
registerReceiver(receiver, filter);
}
//接收器類
private class InnerBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if(Consts.ACTION_PLAY.equals(action)){
play();
}else if(Consts.ACTION_PAUSE.equals(action)){
pause();
}else if(Consts.ACTION_PLAY_NEXT.equals(action)){
next();
}else if(Consts.ACTION_PLAY_PREVIOUS.equals(action)){
previous();
}else if(Consts.ACTION_PLAY_MODE.equals(action)){
playMode=intent.getIntExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_LOOP);
}
//獲取並判斷當前是否需要發送更新進度的廣播
else if(Consts.ACTION_NEED_UPDATE_PROGRESS.equals(action)){
needUpdate=intent.getBooleanExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, true);
if(needUpdate){
synchronized (workThread) {
workThread.notify();
}
//更新進度的時候,同時發送音樂播放器的狀態(是否正在播放、播放的音樂的位置)
Intent intent2=new Intent(Consts.ACTION_SEND_PLAYING_STATE);
int state=Consts.STATE_OTHERS;
int position=0;
if(player.isPlaying()){
state=Consts.STATE_ISPLAYING;
}else if(isPause){
state=Consts.STATE_PAUSE;
}
position=player.getCurrentPosition();
intent2.putExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, position);
intent2.putExtra(Consts.EXTRA_PLAY_STATE, state);
sendBroadcast(intent2);
}
//根據拖動的位置,計算應當開始播放的時間值
}else if(Consts.ACTION_SEEK_TO.equals(action)){
int progress=intent.getIntExtra(Consts.EXTRA_SEEK_TO, player.getCurrentPosition());
int duration=(int)app.getCurrentMusic().getDuration();
seekTo(progress*duration/100);
}else if(Consts.ACTION_APP_STOPED.equals(action)){
stopSelf();
}
}
}
}
package com.tarena.day1901;
import java.io.IOException;
import java.util.Random;
import com.tarena.entity.Music;
import com.tarena.utils.Consts;
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.media.MediaPlayer.OnCompletionListener;
import android.os.IBinder;
import android.util.Log;
public class MusicService extends Service {
private MediaPlayer player;
private MusicApplication app;
private boolean isPause;
private boolean needUpdate; //需要發布更新進度
private boolean isLoop;//控制循環語句
private int playMode;
private Random random;
private InnerBroadcastReceiver receiver;
private Thread workThread;
@Override
public void onCreate() {
super.onCreate();
app=(MusicApplication)getApplication();
player=new MediaPlayer();
playMode=Consts.PLAY_MODE_LOOP;
isLoop=true;
needUpdate=true;
random=new Random();
//設置自動播放下一首的監聽器
addlistener();
//添加接收器
createReceiver();
workThread=new Thread(){
public void run() {
while(isLoop){
while(isLoop&&needUpdate&&player.isPlaying()){
Intent intent=new Intent(Consts.ACTION_START_UPDATE_PROGRESS);
//將當前播放的音樂播放的時間抽的位置包裝傳遞
intent.putExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, player.getCurrentPosition());
sendBroadcast(intent);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//此工作線程需要不停地循環工作,除非修改循環標志。不需要發送廣播的時候就等待,睡大覺
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
};
workThread.start();
}
//service銷毀的時候,解除注冊廣播接收器
@Override
public void onDestroy() {
unregisterReceiver(receiver);
//喚醒線程,讓線程退出循環
isLoop = false;
synchronized (workThread) {
workThread.notify();
}
//如果音樂還在播放,停止其播放
if (player.isPlaying())
player.stop();
//釋放資源
player.release();
super.onDestroy();
}
//如果是isPause狀態值為true,直接播放,else重置player,最後要記得喚醒線程
public void play(){
if(isPause){
player.start();
}else{
Music music=app.getCurrentMusic();
String path=music.getMusicPath();
if(path!=null){
try {
player.reset();
player.setDataSource(path);
player.prepare();
player.start();
//當前索引所表示的歌曲變化,發布廣播
Intent intent=new Intent(Consts.ACTION_CURRENT_MUSIC_CHANGE);
sendBroadcast(intent);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
isPause=false;//音樂開始播放,將暫停狀態標志置為false
synchronized (workThread) {
workThread.notify();
}
}
//如果正在播放,暫停播放
public void pause(){
if(player.isPlaying()){
player.pause();
isPause=true;
}
}
//開始播放後一首
public void next(){
int index=app.getCurrentPosition();
switch (playMode) {
case Consts.PLAY_MODE_LOOP:
if(++index>=app.getPlayListSize()){
index=0;
}
break;
case Consts.PLAY_MODE_RADOM:
do {
index=random.nextInt(app.getPlayListSize());
} while (index==app.getCurrentPosition());
break;
}
app.setCurrentPosition(index);
isPause=false;
play();
}
//開始播放前一首
public void previous(){
int index=app.getCurrentPosition();
switch (playMode) {
case Consts.PLAY_MODE_LOOP:
if(--index<=0){
index=app.getPlayListSize()-1;
}
break;
case Consts.PLAY_MODE_RADOM:
do {
index=random.nextInt(app.getPlayListSize());
} while (index==app.getCurrentPosition());
break;
}
app.setCurrentPosition(index);
isPause=false;
play();
}
//定位到指定的時間值開始播放
public void seekTo(int positon){
player.seekTo(positon);
player.start();
synchronized (workThread) {
workThread.notify();
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
//設置自動播放下一首
public void addlistener(){
player.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
next();
}
});
}
//添加接收器
private void createReceiver() {
receiver=new InnerBroadcastReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction(Consts.ACTION_PAUSE);
filter.addAction(Consts.ACTION_PLAY);
filter.addAction(Consts.ACTION_PLAY_NEXT);
filter.addAction(Consts.ACTION_PLAY_PREVIOUS);
filter.addAction(Consts.ACTION_PLAY_MODE);
filter.addAction(Consts.ACTION_APP_STOPED);
filter.addAction(Consts.ACTION_NEED_UPDATE_PROGRESS);
filter.addAction(Consts.ACTION_SEEK_TO);
registerReceiver(receiver, filter);
}
//接收器類
private class InnerBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if(Consts.ACTION_PLAY.equals(action)){
play();
}else if(Consts.ACTION_PAUSE.equals(action)){
pause();
}else if(Consts.ACTION_PLAY_NEXT.equals(action)){
next();
}else if(Consts.ACTION_PLAY_PREVIOUS.equals(action)){
previous();
}else if(Consts.ACTION_PLAY_MODE.equals(action)){
playMode=intent.getIntExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_LOOP);
}
//獲取並判斷當前是否需要發送更新進度的廣播
else if(Consts.ACTION_NEED_UPDATE_PROGRESS.equals(action)){
needUpdate=intent.getBooleanExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, true);
if(needUpdate){
synchronized (workThread) {
workThread.notify();
}
//更新進度的時候,同時發送音樂播放器的狀態(是否正在播放、播放的音樂的位置)
Intent intent2=new Intent(Consts.ACTION_SEND_PLAYING_STATE);
int state=Consts.STATE_OTHERS;
int position=0;
if(player.isPlaying()){
state=Consts.STATE_ISPLAYING;
}else if(isPause){
state=Consts.STATE_PAUSE;
}
position=player.getCurrentPosition();
intent2.putExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, position);
intent2.putExtra(Consts.EXTRA_PLAY_STATE, state);
sendBroadcast(intent2);
}
//根據拖動的位置,計算應當開始播放的時間值
}else if(Consts.ACTION_SEEK_TO.equals(action)){
int progress=intent.getIntExtra(Consts.EXTRA_SEEK_TO, player.getCurrentPosition());
int duration=(int)app.getCurrentMusic().getDuration();
seekTo(progress*duration/100);
}else if(Consts.ACTION_APP_STOPED.equals(action)){
stopSelf();
}
}
}
}
Android上在兩個Activity之間傳遞Bitmap對象因為我做Android應用的時間不長,所以當我第一次在android之間傳遞Bitmap對象的時候我直接用了
借助SQLiteOpenHelper幫助類實現對數據庫的創建和升級。MainActivity.javapackage com.example.databasetest;i
上篇博客中我們提到了OpenGLES中繪制的兩種方法,頂點法和索引法。之前我們所使用的都是頂點法,這次繪制立方體使用索引法來繪制立方體。構建立方體上篇博客講到正方形的繪制
RecyclerView 水平多行排列添加頭和尾import android.content.Context;import android.support.v7.widg