【郭林专刊】Android Music

来源:互联网 发布:电器仿真软件 编辑:程序博客网 时间:2024/04/29 03:09
 

音乐播放器中综合了以下内容:

SeekBar、ListView、广播接收者(以代码的形式注册Receiver)、系统服务、MediaPlayer

实现的功能:

1.暂停/播放、下一首/上一首,点击某一首时播放

2.支持拖动进度条快进

3.列表排序

4.来电话时,停止播放,挂断后继续播放

5.可在后台播放

 

效果图:

界面:

main.xml:

view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.     <TextView    
  8.         android:id="@+id/name"  
  9.         android:layout_width="fill_parent"   
  10.         android:layout_height="wrap_content"   
  11.         />  
  12.     <SeekBar  
  13.         android:id="@+id/seekBar"  
  14.         android:layout_width="fill_parent"   
  15.         android:layout_height="wrap_content"   
  16.         android:layout_marginBottom="5dp"  
  17.         />  
  18.     <LinearLayout  
  19.         android:layout_width="fill_parent"   
  20.         android:layout_height="wrap_content"   
  21.         android:layout_marginBottom="20dp"  
  22.         >  
  23.         <Button  
  24.             android:layout_width="40dp"   
  25.             android:layout_height="40dp"   
  26.             android:text="|◀"  
  27.             android:onClick="previous"  
  28.             />  
  29.         <Button  
  30.             android:id="@+id/pp"  
  31.             android:layout_width="40dp"   
  32.             android:layout_height="40dp"   
  33.             android:text="▶"  
  34.             android:onClick="pp"  
  35.             />  
  36.         <Button  
  37.             android:layout_width="40dp"   
  38.             android:layout_height="40dp"   
  39.             android:text="▶|"  
  40.             android:onClick="next"  
  41.             />  
  42.     </LinearLayout>  
  43.     <ListView  
  44.         android:id="@+id/list"  
  45.         android:layout_width="fill_parent"   
  46.         android:layout_height="fill_parent"   
  47.         />  
  48. </LinearLayout>  


item.xml:

view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="wrap_content"  
  6.     android:padding="10dp"  
  7.     >  
  8.     <TextView  
  9.         android:id="@+id/mName"  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:textSize="15sp"  
  13.         />  
  14. </LinearLayout>  

MainActivity:

view plaincopy to clipboardprint?
  1. package cn.test.audio;  
  2.   
  3. import java.io.File;  
  4. import java.util.ArrayList;  
  5. import java.util.Collections;  
  6. import java.util.HashMap;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9.   
  10. import android.app.Activity;  
  11. import android.content.BroadcastReceiver;  
  12. import android.content.Context;  
  13. import android.content.Intent;  
  14. import android.content.IntentFilter;  
  15. import android.media.MediaPlayer;  
  16. import android.media.MediaPlayer.OnCompletionListener;  
  17. import android.os.Bundle;  
  18. import android.os.Environment;  
  19. import android.os.Handler;  
  20. import android.telephony.PhoneStateListener;  
  21. import android.telephony.TelephonyManager;  
  22. import android.view.View;  
  23. import android.widget.AdapterView;  
  24. import android.widget.Button;  
  25. import android.widget.ListView;  
  26. import android.widget.SeekBar;  
  27. import android.widget.SimpleAdapter;  
  28. import android.widget.TextView;  
  29. import android.widget.AdapterView.OnItemClickListener;  
  30. import android.widget.SeekBar.OnSeekBarChangeListener;  
  31.   
  32. public class MainActivity extends Activity {  
  33.     private TextView nameTextView;  
  34.     private SeekBar seekBar;  
  35.     private ListView listView;  
  36.     private List<Map<String, String>> data;  
  37.     private int current;  
  38.     private MediaPlayer player;  
  39.     private Handler handler = new Handler();  
  40.     private Button ppButton;  
  41.     private boolean isPause;  
  42.     private boolean isStartTrackingTouch;  
  43.   
  44.     public void onCreate(Bundle savedInstanceState) {   
  45.         super.onCreate(savedInstanceState);  
  46.         setContentView(R.layout.main);  
  47.   
  48.         nameTextView = (TextView) findViewById(R.id.name);  
  49.         seekBar = (SeekBar) findViewById(R.id.seekBar);  
  50.         listView = (ListView) findViewById(R.id.list);  
  51.         ppButton = (Button) findViewById(R.id.pp);  
  52.           
  53.         //创建一个音乐播放器   
  54.         player = new MediaPlayer();  
  55.   
  56.         //显示音乐播放列表   
  57.         generateListView();  
  58.   
  59.         //进度条监听器   
  60.         seekBar.setOnSeekBarChangeListener(new MySeekBarListener());  
  61.           
  62.         //播放器监听器   
  63.         player.setOnCompletionListener(new MyPlayerListener());  
  64.   
  65.         //意图过滤器   
  66.         IntentFilter filter = new IntentFilter();  
  67.           
  68.         //播出电话暂停音乐播放   
  69.         filter.addAction("android.intent.action.NEW_OUTGOING_CALL");  
  70.         registerReceiver(new PhoneListener(), filter);  
  71.   
  72.         //创建一个电话服务   
  73.         TelephonyManager manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);  
  74.           
  75.         //监听电话状态,接电话时停止播放   
  76.         manager.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);  
  77.     }  
  78.   
  79.     /* 
  80.      * 监听电话状态 
  81.      */  
  82.     private final class MyPhoneStateListener extends PhoneStateListener {  
  83.         public void onCallStateChanged(int state, String incomingNumber) {  
  84.             pause();  
  85.         }  
  86.     }  
  87.   
  88.     /* 
  89.      * 播放器监听器 
  90.      */  
  91.     private final class MyPlayerListener implements OnCompletionListener {  
  92.         //歌曲播放完后自动播放下一首歌曲   
  93.         public void onCompletion(MediaPlayer mp) {  
  94.             next();  
  95.         }  
  96.     }  
  97.   
  98.     /* 
  99.      * 下一首按钮 
  100.      */  
  101.     public void next(View view) {  
  102.         next();  
  103.     }  
  104.   
  105.     /* 
  106.      * 前一首按钮 
  107.      */  
  108.     public void previous(View view) {  
  109.         previous();  
  110.     }  
  111.   
  112.     /* 
  113.      * 播放前一首歌 
  114.      */  
  115.     private void previous() {  
  116.         current = current - 1 < 0 ? data.size() - 1 : current - 1;  
  117.         play();  
  118.     }  
  119.   
  120.     /* 
  121.      * 播放下一首歌 
  122.      */  
  123.     private void next() {  
  124.         current = (current + 1) % data.size();  
  125.         play();  
  126.     }  
  127.   
  128.     /* 
  129.      * 进度条监听器 
  130.      */  
  131.     private final class MySeekBarListener implements OnSeekBarChangeListener {  
  132.         //移动触发   
  133.         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {  
  134.         }  
  135.   
  136.         //起始触发   
  137.         public void onStartTrackingTouch(SeekBar seekBar) {  
  138.             isStartTrackingTouch = true;  
  139.         }  
  140.   
  141.         //结束触发   
  142.         public void onStopTrackingTouch(SeekBar seekBar) {  
  143.             player.seekTo(seekBar.getProgress());  
  144.             isStartTrackingTouch = false;  
  145.         }  
  146.     }  
  147.   
  148.     /* 
  149.      * 显示音乐播放列表 
  150.      */  
  151.     private void generateListView() {  
  152.         List<File> list = new ArrayList<File>();  
  153.           
  154.         //获取sdcard中的所有歌曲   
  155.         findAll(Environment.getExternalStorageDirectory(), list);  
  156.           
  157.         //播放列表进行排序,字符顺序   
  158.         Collections.sort(list);  
  159.   
  160.         data = new ArrayList<Map<String, String>>();  
  161.         for (File file : list) {  
  162.             Map<String, String> map = new HashMap<String, String>();  
  163.             map.put("name", file.getName());  
  164.             map.put("path", file.getAbsolutePath());  
  165.             data.add(map);  
  166.         }  
  167.   
  168.         SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item, new String[] { "name" }, new int[] { R.id.mName });  
  169.         listView.setAdapter(adapter);  
  170.   
  171.         listView.setOnItemClickListener(new MyItemListener());  
  172.     }  
  173.   
  174.     private final class MyItemListener implements OnItemClickListener {  
  175.         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  
  176.             current = position;  
  177.             play();  
  178.         }  
  179.     }  
  180.   
  181.       
  182.     private void play() {  
  183.         try {  
  184.             //重播   
  185.             player.reset();  
  186.               
  187.             //获取歌曲路径   
  188.             player.setDataSource(data.get(current).get("path"));  
  189.               
  190.             //缓冲   
  191.             player.prepare();  
  192.               
  193.             //开始播放   
  194.             player.start();  
  195.               
  196.             //显示歌名   
  197.             nameTextView.setText(data.get(current).get("name"));  
  198.               
  199.             //设置进度条长度   
  200.             seekBar.setMax(player.getDuration());  
  201.   
  202.             //播放按钮样式   
  203.             ppButton.setText("||");  
  204.   
  205.             //发送一个Runnable, handler收到之后就会执行run()方法  
  206.             handler.post(new Runnable() {  
  207.                 public void run() {  
  208.                     // 更新进度条状态   
  209.                     if (!isStartTrackingTouch)  
  210.                         seekBar.setProgress(player.getCurrentPosition());  
  211.                     // 1秒之后再次发送  
  212.                     handler.postDelayed(this1000);  
  213.                 }  
  214.             });  
  215.         } catch (Exception e) {  
  216.             e.printStackTrace();  
  217.         }  
  218.     }  
  219.   
  220.     /** 
  221.      * 查找文件路径中所有mp3文件 
  222.      * @param file 要找的目录 
  223.      * @param list 用来装文件的List 
  224.      */  
  225.     private void findAll(File file, List<File> list) {  
  226.         File[] subFiles = file.listFiles();  
  227.         if (subFiles != null)  
  228.             for (File subFile : subFiles) {  
  229.                 if (subFile.isFile() && subFile.getName().endsWith(".mp3"))  
  230.                     list.add(subFile);  
  231.                 else if (subFile.isDirectory())//如果是目录  
  232.                     findAll(subFile, list); //递归  
  233.             }  
  234.     }  
  235.   
  236.     /* 
  237.      * 暂停/播放按钮 
  238.      */  
  239.     public void pp(View view) {  
  240.           
  241.         //默认从第一首歌曲开始播放   
  242.         if (!player.isPlaying() && !isPause) {  
  243.             play();  
  244.             return;  
  245.         }  
  246.   
  247.         Button button = (Button) view;  
  248.         //暂停/播放按钮   
  249.         if ("||".equals(button.getText())) {  
  250.             pause();  
  251.             button.setText("▶");  
  252.         } else {  
  253.             resume();  
  254.             button.setText("||");  
  255.         }  
  256.     }  
  257.   
  258.     /* 
  259.      * 开始操作 
  260.      */  
  261.     private void resume() {  
  262.         if (isPause) {  
  263.             player.start();  
  264.             isPause = false;  
  265.         }  
  266.     }  
  267.   
  268.     /* 
  269.      * 暂停操作 
  270.      */  
  271.     private void pause() {  
  272.         if (player != null && player.isPlaying()) {  
  273.             player.pause();  
  274.             isPause = true;  
  275.         }  
  276.     }  
  277.   
  278.     /* 
  279.      * 收到广播时暂停 
  280.      */  
  281.     private final class PhoneListener extends BroadcastReceiver {  
  282.         public void onReceive(Context context, Intent intent) {  
  283.             pause();  
  284.         }  
  285.     }  
  286.   
  287.     /* 
  288.      * 恢复播放 
  289.      * @see android.app.Activity#onResume() 
  290.      */  
  291.     protected void onResume() {  
  292.         super.onResume();  
  293.         resume();  
  294.     }  
  295. }  


注册权限:

view plaincopy to clipboardprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="cn.itcast.audio"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  7.         <activity android:name=".MainActivity"  
  8.                   android:label="@string/app_name">  
  9.             <intent-filter>  
  10.                 <action android:name="android.intent.action.MAIN" />  
  11.                 <category android:name="android.intent.category.LAUNCHER" />  
  12.             </intent-filter>  
  13.         </activity>  
  14.   
  15.     </application>  
  16.     <uses-sdk android:minSdkVersion="8" />  
  17.       
  18.     <!-- 监听电话呼出 -->  
  19.     <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>  
  20.     <!-- 监听电话状态改变 -->  
  21.     <uses-permission android:name="android.permission.READ_PHONE_STATE" />   
  22.   
  23. </manifest>   

非常反感源码  但是还是共享一下  帮助大家共同学习。。。。。

原创粉丝点击