編輯:關於android開發
最近做一個項目,有一個功能模塊,需要播放音頻,畫一個簡單的界面
一個例子:
我們都知道播放音頻要用到MediaPlayer類,我這裡,不需要開啟Service,就在本Activity播放音頻,當Activity銷毀的時候,音頻便結束
但是有一個重點,需要即時的變化當前播放的時間
我的思路是,開啟一個線程,計算當前音頻的剩余播放時間,如果>0 則用Handler循環發送一個消息來更改時間UI
Thread tPlay ; tPlay = new Thread(new Runnable() { @Override public void run() { int time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000; // 獲得當前的音頻的剩余時間,總時長-當前播放時長 while(time>0&&mPlay!=null) { // 如果剩余時間>0 並且MediaPlayer對象存在,就需要沒0.2秒更新一下時間UI try { Thread.sleep(200); time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000; //獲得當前時間 final int finalTime = time; handler.post(new Runnable() { @Override public void run() { topic_play_time.setText(finalTime /60+"'"+ finalTime %60); //更改UI } }); } catch (InterruptedException e) { e.printStackTrace(); } } } });
然後有線程對象了,什麼時候start呢,必然是在第一次播放音頻的時候,而且只能start一次。
那麼問題來了。當我播放音頻的時候,或者暫停已經播放一段的音頻的時候,用戶可能會退出Activity ,
而Activity銷毀了,但是這個Activity開啟的計算時間更改UI的子線程還存在,它還需要循環計算剩余時間,但是MediaPlayer對象沒了,就報錯了。
所以,解決方法只能是銷毀Activity之前結束這個Activity開啟的子線程。
試過幾種方法,最後選定了一個最簡單,最易理解的方法:
即
1、設置一個全局標記變量boolean flag = true;
2、線程中while 循環判斷 flag 是否為true,是則執行內部代碼,否則不執行,結束循環了,即線程也隨之結束了
tPlay = new Thread(new Runnable() { @Override public void run() { int time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000; while(time>0&&mPlay!=null&&flag) { } } });
3、在Activity銷毀的
@Override protected void onDestroy() { super.onDestroy(); isflag=false; }
方法中更改flag,那麼線程中while條件則不成立,線程就結束了,也不會再報錯了。
貼一下關鍵代碼:
1 public class TopicDetailActivity extends Activity implements View.OnClickListener { 2 3 private ImageButton topic_play_music; 4 5 private Attention entity; 6 7 private boolean isflag= true; 8 private MediaPlayer mPlay; 9 private Thread tPlay; 10 private Handler handler = new Handler(){ 11 @Override 12 public void handleMessage(Message msg) { 13 super.handleMessage(msg); 14 15 } 16 }; 17 @Override 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.activity_topic_detail); 21 22 Intent intent = getIntent(); 23 Serializable attention = intent.getSerializableExtra("attention"); 24 tPlay = new Thread(new Runnable() { 25 @Override 26 public void run() { 27 int time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000; 28 while(time>0&&mPlay!=null&&isflag) { 29 try { 30 Thread.sleep(200); 31 time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000; 32 final int finalTime = time; 33 handler.post(new Runnable() { 34 @Override 35 public void run() { 36 topic_play_time.setText(finalTime /60+"'"+ finalTime %60); 37 } 38 }); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } 42 } 43 } 44 }); 45 initView(); 46 initData(attention); 47 } 48 49 /** 50 * 數據展示 51 * @param attention 52 */ 53 private void initData(Serializable attention) { 54 entity = (Attention) attention; 55 56 int nowTime = Integer.parseInt(entity.getAudiolength()); 57 topic_play_time.setText(nowTime/60 + "'" + nowTime%60); 58 59 60 61 62 } 63 64 65 /** 66 * 初始化控件 67 */ 68 private void initView() { 69 topic_play_music = (ImageButton) findViewById(R.id.topic_play_music); 70 71 topic_play_music.setOnClickListener(this); 72 } 73 74 @Override 75 public void onClick(View v) { 76 switch (v.getId()){ 77 78 case R.id.topic_play_music: 79 if(mPlay==null){ 80 mPlay = new MediaPlayer(); 81 mPlay.reset(); 82 try { 83 mPlay.setDataSource("http://imagecdn.xunjimap.com/image/" + entity.getAudiourl()); 84 mPlay.prepare(); 85 topic_play_music.setImageResource(R.mipmap.ui_detail_pause); 86 mPlay.start(); 87 tPlay.start(); 88 } catch (IOException e) { 89 e.printStackTrace(); 90 } 91 }else{ 92 if (mPlay.isPlaying()){ 93 mPlay.pause(); 94 topic_play_music.setImageResource(R.mipmap.ui_detail_play); 95 }else{ 96 mPlay.start(); 97 topic_play_music.setImageResource(R.mipmap.ui_detail_pause); 98 } 99 } 100 break; 101 } 102 } 103 104 @Override 105 protected void onDestroy() { 106 super.onDestroy(); 107 isflag=false; 108 try { 109 tPlay.sleep(500); 110 } catch (InterruptedException e) { 111 e.printStackTrace(); 112 } 113 if (mPlay!=null){ 114 mPlay.stop(); 115 116 mPlay.release(); 117 } 118 } 119 120 121 } 122 123 關鍵代碼 關鍵代碼
關於Android中圖片大小、內存占用與drawable文件夾關系的研究與分析 從上一篇文章《Android屏幕適配全攻略》寫完之後,經常會有朋友問我這個問題:&ldq
《Android源碼設計模式解析與實戰》讀書筆記(二十三) 第二十三章、外觀模式 外觀模式是結構型設計模式之一,它在開發中的運用頻率非常高,是我們封裝API的常用手段。
安卓動態調試七種武器之孔雀翎 – Ida Pro,安卓ida安卓動態調試七種武器之孔雀翎 – Ida Pro 作者:蒸米@阿裡聚安全 0x00
activity切換動畫特效,activity切換特效效果圖: 結構圖: 測試代碼: 布局: 1 <?xml version=1.