当前位置:文档之家› 安卓音乐播放器开发含源代码

安卓音乐播放器开发含源代码

基于an droid平台的音乐播放器开发实验报告学生姓名:_______ 温从林 _________________学号: ___________________________________班级:计自1201 _____________第一章引言1.1项目背景当今社会的生活节奏越来越快,人们对手机的要求也越来越高,由于手机市场发展迅速,使得手机操作系统也出现了不同各类,现在的市场上主要有三个手机操作系统,Win dowsmobile,symbia n,以及谷歌的An droid操作系统,其中占有开放源代码优势的An droid系统有最大的发展前景。

那么能否在手机上拥有自己编写的个性音乐播放器呢?能的,谷歌An droid系统就能做到。

本文的音乐播放器就是基于谷歌An droid手机平台的播放器。

An droid :是谷歌于2007年公布的开放式源代码手机系统,它的开放性就优于其它封闭式的手机系统,因此,任何人都可能根据自己的喜好将手机系统中的所有功能重新编写。

这使得越来越多的人关注这个操作系统。

本次作品音乐播放器就是基于An droid平台的。

1.2编写目的现今社会生活紧张,而欣赏音乐是其中最好的舒缓压力的方式之一,本项目的目的是开发一个可以播放主流音乐文件格式的播放器,本设计实现的主要功能是播放Mp3 Wav多种格式的音乐文件,并且能够控制播放,暂停,停止,播放列等基本播放控制功能,界面简明,操作简单。

本项目是一款基于An droid手机平台的音乐播放器,使An droid手机拥有个性的多媒体播放器,使手机显得更生动灵活化,与人们更为接近,让手机主人随时随地处于音乐视频的旋律之中。

使人们的生活更加多样化。

也使设计者更加熟练An droid的技术和其它在市场上的特点。

1.3开发环境Eclipse、An droid SDK 320第二章系统需求分析2.1功能需求(用例图分析)根据项目的目标,我们可获得项目系统的基本需求,以下从不同角度来描述系统的需求,并且使用用例图来描述,系统的功能需求,我们分成四部分来概括,即播放器的基本控制需要,播放列表管理需求,播放器友好性需求和播放器扩展卡需求。

以下分别描述:2.1.1播放器的用例图假设安装了音乐播放器的用户是系统的主要设计对象,其拥有以下操作,启动软件、播放音乐、暂停播放、停止播放、退出软件,其用例图如下图2.1 播放器基本用例图2.1.2用例分析用例名称:退出参与者:用户目标:使得用户退出或者后台播放音乐前置条件:程序在运行基本事件流:1.用户按返回键2. 播放器退出或者进入后台播放第三章概要设计3.1软件播放流程图Stepl.启动软件后,软件自动检索手机和sd卡的音频文件,并组织显示成列表Step2.点击列表的歌曲名字。

Step3.播放音乐。

Step4.点击暂停,音乐暂停Step5.点击播放转到step3Step6.点击停止停止播放音乐Step7 .点击退出。

自动检索手机中暂停/退出软件图3.1音乐播放器流第四章界面展示4.1 软件部署系统编译生成apk 文件,将apk 文件拷到手机或者sd 卡中,直接打开即可安装。

4.2 启动软件打开软件后的界面4.3 歌曲列表界面歌曲列表界面4.4 播放界面4.5 收藏界面4.6 在线搜索音乐界面第五章结论(1) 通过本次幵发解决了诸如SD卡音乐文件搜索并显示、联网搜索歌曲等难题,对安卓的开发有了更深入的认识。

(2) 通过对Android 手机平台的音乐播放器软件的开发,使我对Android 音乐播放器系统的整体设计有一个深入的了解,对整个流程也会有一个清晰的认识。

开发Android 音乐播放器,要抓住开发的核心部分,音乐播放器大体由播放主界面、播放列表、菜单、播放设置、文件浏览、歌曲搜索六大核心组成。

(3) 本次程序设计,对播放器的系统结构框架做了精心的构思与设计,采用主要开发工具是Eclips4.0+Java 语言的支持,Android Development Tool 的插件,和Android SDK2.1 版本的全面结合,才使整个音乐播放器系统得以实现第五章部分源代码以下给出功能实现代码,布局,风格等代码量过大,放在压缩文件中MainActivity.java:packageimportimportimportimportimportimportimportimportimportimportpublic class MainActivity extends ActionBarActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super .onCreate(savedInstanceState);requestWindowFeature(Window. FEATURE_NO_TITLE);setContentView(yout. fragment_main );Thread thread = new Thread() {public void run() {try {sleep (2500);} catch (InterruptedException e) {e.printStackTrace();}finish();Intent intent = new Intent(MainActivity. this , MusicActivity. class ); startActivity(intent);}};thread.start();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu. main , menu);return true ;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) { //Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId();if (id == R.id. action_settings ) {return true ;}return super .onOptionsItemSelected(item);}* A placeholder fragment containing a simple view. */public static class PlaceholderFragment extends Fragment {public PlaceholderFragment() {}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View rootView = inflater.inflate(yout. fragment_main false );, container, return rootView;}}}BandanActivity.javapackage ;importimportimportimportimportimportimportimportimportimportimportimportimportsuper .onCreate(savedInstanceState);setContentView(yout. bangdanmusic_list );listview = (ListView) findViewById(R.id. bangdan_music_list );listview .setOnItemClickListener( new MusicListOnClickListener()); ShowMp3List(); }*显示MP3言息,其中」ds 保存了所有音乐文件的_ID ,用来确定到底要播放哪一首歌曲,_titles 存放音乐名,用来显示在播放界面,*而_path 存放音乐文件的路径(删除文件时会用到)*/private void ShowMp3List() {// 用游标查找媒体详细信息this .getContentResolver().query(DISPLAY_NAME , // 显示名称 ,4cursor.moveToFirst();/** 分别将各个标题数组实例化 **/ _ids = new int [cursor.getCount()];_titles = new String[cursor.getCount()];_artists = new String[cursor.getCount()];_path =new Strin g[cursor.getCo un t()]; _album =new Strin g[cursor.getCo un t()]; privateListView listview ; privateString musicpath ; privateint _ids []; // 存放音乐文件的 id 数组 privateString _titles []; // 存放音乐文件的标题数组 privateString _artists []; // 存放音乐艺术家的标题数组 privateString[] _path ; // 存放音乐路径的标题数组 privateString[] _times ; // 存放总时间的标题数组 privateString[] _album ; // 存放专辑的标题数组 privateint _sizes []; // 存放文件大小的标题数组 private String[] displayname ; // 存放名称的标题数组@Overrideprotected void onCreate(Bundle savedInstanceState) {extends Activity { public class BangdanActivityCursor cursor = EXTERNAL_CONTENT new String[] {TITLE ,DURATION ,ARTIST , , UR ,I// 标题,游标从 0读取 // 持续时间 ,1 // 艺术家 ,2 // id ,3 DATA ,ALBUM_ID , ALBUM ,SIZE }, null/** 将游标移到第一位 **/ // 数据, 5 // 专辑名称 ID ,6// 专辑 ,7 , null ART IST ); // 大小 ,8_times = new Strin g[cursor.getCo un t()];_displa yn ame = new Strin g[cursor.getCo un t()];_sizes = new int [cursor.getCount()];到的内容格式为/mnt/sdcard/[ 子文件夹名/]音乐文件名,而我们想要得到的是/sdcard/[ 子文件夹名]音乐文件名*/for (int i = 0; i < cursor.getCount(); i++) {_ids [i] = cursor.getInt(3);_titles [i] = cursor.getStri ng(0);_artists [i] = cursor.getStri ng(2);_path [i] = cursor.getString(5).substring(4);/***** 以下是为提供音乐详细信息而生成的******/_album [i] = cursor.getString(7);_times [i] = toTime(cursor.getInt(1));_sizes [i] = cursor.getInt(8);_displa yn ame [i] = cursor.getStri ng(4);cursor.moveToNext();}listview .setAdapter( new MusicListAdapter( this , cursor));}/**时间的转换*/public String toTime( int time) {time /= 1000;int minute = time / 60;int second = time % 60;minute %= 60;/**返回结果用string 的format方法把时间转换成字符类型**/return Stri ng. format ("%02d:%02d" , min ute, seco nd);}/**音乐列表添加监听器,点击之后播放音乐*/public class MusicList On ClickListe ner impleme nts On ItemClickListe ner { @Overridepublic void on ltemClick(AdapterView<?>argO, View view, int positi on, long id) {musicpath ="/mnt" +_path [position];playMusic( musicpath );/*putExtraMusic(positio n); */Intent intent = new Inten t(Ba ngda nActivity. this PlayMusicActivity. class );startActivity(i ntent);fin ish();}}public void playMusic(String musicpath) {try {MediaPlayer mp = new MediaPlayer();mp.reset();mp.setDataSource(musicpath);mp.prepare();mp.start();} catch (Exception e){Toast. makeText (getApplicationContext(), Toast. LENGTH_SHOR)T.show();}}public void putExtraMusic( int position) { Intent intentIntent(BangdanActivity. this ,PlayMusicActivity. class );/*intent.putExtra("_ids", _ids);intent.putExtra("_path", _path);intent.putExtra("_titles", _titles);intent.putExtra("_artists", _artists);intent.putExtra("position", position);startActivity(intent);finish();*/intent = new Intent();Bundle bundle = new Bundle();bundle.putInt( "position" , 25);intent.putExtras(bundle);intent.setClass(BangdanActivity. this , PlayMusicActivity. class ); startActivity(intent);finish();}@Overrideprotected void onStop() {super .onStop();}private long exitTime = 0;public boolean onKeyDown( int keyCode, KeyEvent event) {if (keyCode == KeyEvent. KEYCODE_BACK && event.getAction() KeyEvent.ACTION_DOWN){if ((System. currentTimeMillis ()- exitTime ) > 2000){Toast. makeText (getApplicationContext(), " 再按一次退出程序 Toast.LENGTH_SHOR)T.show();exitTime = System. currentTimeMillis ();else {finish();System. exit (0);}return true ;无法播放此文件new}return super .onKeyDown(keyCode, event);}}CollectionActivity.javapublic class CollectionActivity extends ExpandableListActivity { @Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 一级条目List<Map<String, String>>groups=new ArrayList<Map<String,String>>();Map<String, String> group1=new HashMap<String, String>();group1.put("group"," 【歌手】");Map<String, String> group2=new HashMap<String, String>();group2.put("group"," 【专辑】");groups.add(group1);groups.add(group2);// 二组条目List<List<Map<String, String>>> childs=newArrayList<List<Map<String,String>>>();// 第一组二级科目数据List<Map<String, String>> ArrayList<Map<String,String>>(); Map<String, String> item1=new HashMap<String, String>(); item1.put("child"," 林俊杰");Map<String, String> item2=new HashMap<String, String>(); item2.put("child"," 周杰伦");child1.add(item1);child1.add(item2);// 第二组二级科目数据List<Map<String, String>> ArrayList<Map<String,String>>(); Map<String, String> item3=new HashMap<String, String>(); item3.put("child","<< 因你而在>>");Map<String, String> item4=new HashMap<String, String>(); item4.put("child","<< 流行主教>>");Map<String, String> item5=new HashMap<String, String>(); item5.put("child","<< 第二天堂>>");child2.add(item3);child2.add(item4);child2.add(item5);childs.add(child1); child1=new child2=newchilds.add(child2);//SimpleExpandableListAdapter构造函数参数//1.content//2. 一级条目数据//3. 一级条目布局文件// 4 . 一级条目Key//5. 一级条目显示信息控件id//6. 二级条目数据//7. 二级条目布局文件//8. 二级条目Key//9. 二级条目显示信息控件idsetListAdapter(adapter);}private long exitTime = 0;public boolean onKeyDown(int keyCode, KeyEvent event) {if(keyCode == KeyEvent.KEYCODE_BACK&& event.getAction() KeyEvent.ACTION_DOWN){if((System.currentTimeMillis()-exitTime) >2000){ Toast.makeText(getApplicationContext(), " 再按一次退出程序", Toast.LENGTH_SHORT).show();exitTime = System.currentTimeMillis();}else { finish();System.exit(0);}return true;}return super.onKeyDown(keyCode, event);}/*** 初始化菜单*/public boolean onMenuKeyDown(int keyCode, KeyEvent event) { if(keyCode==KeyEvent.KEYCODE_MENU&& event.getAction() = KeyEvent.ACTION_DOWN){Toast.makeText(getApplicationContext(), " 未定义菜单" Toast.LENGTH_SHORT).show();}return true;}}Contsant.javapublic class Contsant {* 获取屏幕的大小0:宽度1 :高度}**/public static int[] getScreen(Context context) { WindowManager windowManagercontext.getSystemService(Context.WINDOW_SERVICE);Display display = windowManager.getDefaultDisplay();DisplayMetrics outMetrics = new DisplayMetrics(); display.getMetrics(outMetrics);return new int[] { (int) (outMetrics.density * outMetrics.widthPixels), (int)(outMetrics.density * outMetrics.heightPixels) };}/**获取文件的后缀名,返回大写**/ public static String getSuffix(String str) {int i = stIndexOf('.');if (i != -1) {return str.substring(i + 1).toUpperCase(); } return str;}/**格式化文件大小Byte->MB**/public static String formatByteToMB(int size){ float mb=size/1024f/1024f;return String.format("%.2f",mb);LRCbean.javapackage/** 歌词实体*/public class LRCbean {private int beginTime = 0; // 开始时间public int getBeginTime() {return beginTime;}public void setBeginTime( int beginTime) { this .beginTime = beginTime;}public int getLineTime() {return lineTime;(WindowManager)public void setLineTime( int lineTime) { this .lineTime = lineTime;}public String getLrcBody() { return lrcBody;public void setLrcBody(String lrcBody) {this .lrcBody = lrcBody;}private int lineTime = 0;private String lrcBody = null ; // 歌词实体}MDialog.java* 自定义的对话框*/public class MDialog extends Dialog {public MDialog(Context context) {super(context);}public MDialog(Context context, int theme) { super(context, theme);}public static class Builder {private Context context;private int mIcon = -1; // 提示图标private CharSequence mTitle; // 提示标题private CharSequence mMessage;// 提示内容private CharSequence mPositiveButtonText;// privateCharSequence mNegativeButtonText;// privateCharSequence mNeutralButtonText; // private booleanmCancelable = true;//private int mViewSpacingLeft; private int mViewSpacingTop;private int mViewSpacingRight;private int mViewSpacingBottom;private boolean mViewSpacingSpecified = false; // 提示内容Viewprivate View mView; private OnClickListener mPositiveButtonClickListener, mNegativeButtonClickListener, mNeutralButtonClickListener;private OnCancelListener mCancelListener;// private OnKeyListener mKeyListener; //取消键事件按键处理确定按钮文本拒绝按钮文本中间按钮文本是否启用取消键public Builder(Context context) {this.context = context;}public Builder setMessage(CharSequence message) { this.mMessage = message;return this;}public Builder setMessage(int message) { this.mMessage = context.getText(message);return this;}public Builder setTitle(int title) {this.mTitle = context.getText(title); return this;}public Builder setTitle(CharSequence title) {this.mTitle = title;return this;}public Builder setIcon(int icon) {this.mIcon = icon;return this;}public Builder setView(View view) {this.mView = view;mViewSpacingSpecified = false;return this;}public Builder setView(View view, int left, int top, int right, int bottom) {this.mView = view;this.mViewSpacingLeft = left; this.mViewSpacingTop = top; this.mViewSpacingRight = right; this.mViewSpacingBottom = bottom; mViewSpacingSpecified = true; return this; }public Builder setPositiveButton(int textId,final OnClickListener listener) { this.mPositiveButtonText = context.getText(textId);this.mPositiveButtonClickListener = listener; return this;}public Builder setPositiveButton(String text,final OnClickListener listener) { this.mPositiveButtonText = text;this.mPositiveButtonClickListener = listener; return this;}public Builder setNeutralButton(int textId,final OnClickListener listener) { this.mNeutralButtonText = context.getText(textId);this.mNeutralButtonClickListener = listener; return this;}public Builder setNeutralButton(String text,final OnClickListener listener) { this.mNeutralButtonText = text;this.mNeutralButtonClickListener = listener; return this;}public Builder setNegativeButton(int textId,final OnClickListener listener) { this.mNegativeButtonText = context.getText(textId);this.mNegativeButtonClickListener = listener; return this;}public Builder setNegativeButton(String text,final OnClickListener listener) { this.mNegativeButtonText = text;this.mNegativeButtonClickListener = listener; return this;}public Builder setCancelable(boolean cancelable) { this.mCancelable = cancelable;return this;}public Builder setOnCancelListener(OnCancelListener listener) { this.mCancelListener = listener;return this;}public Builder setOnKeyListener(OnKeyListener listener) { this.mKeyListener = listener;return this;}public MDialog create() {LayoutInflater inflater = (LayoutInflater) context.getSystemService(YOUT_INFLATER_SERVICE);dialog.setCancelable(mCancelable);// 设置取消键事件if (mCancelListener != null) {dialog.setOnCancelListener(mCancelListener);}// 设置键盘监听事件if (mKeyListener != null) { dialog.setOnKeyListener(mKeyListener);}// 获取对话框布局layout.setLayoutParams(newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));// 设置标题// 设置图标if (mIcon != -1) {}int count = 0;// 设置确定按钮count++;// 设置拒绝按钮count++;// 设置中间按钮count++;if(count==0){}// 一个按钮时,显示两边空间if (count == 1) {}// 设置提示消息if (!TextUtils.isEmpty(mMessage)) {} else {}// 设置提示内容布局if (mView != null) {if (mViewSpacingSpecified) {customPanel.setPadding(mViewSpacingLeft, mViewSpacingTop,mViewSpacingRight, mViewSpacingBottom);}customPanel.addView(mView);} else {}dialog.setContentView(layout);return dialog;}public MDialog show() {MDialog dialog = create();dialog.show();return dialog;}private boolean setButton(View layout, mPositiveButtonText2, int id,final Dialog dialog, final OnClickListener listener) {CharSequence if (!TextUtils.isEmpty(mPositiveButtonText2)) {final Button button1 = (Button) layout.findViewById(id);button1.setText(mPositiveButtonText2);if (listener != null) {button1.setOnClickListener(new View.OnClickListener(){ public void onClick(View v) {listener.onClick(dialog,DialogInterface.BUTTON_POSITIVE);}});}else{// 默认事件为关闭对话框button1.setOnClickListener(newView.OnClickListener() { public void onClick(View v) {dialog.cancel(); dialog.dismiss();}});}return true;} else { layout.findViewById(id).setVisibility(View.GONE); return false;}}}}MusicActivity.java/* 以Tabhost+RadioGroup 组合*/public class MusicActivity extends TabActivity OnCheckedChangeListener{private TabHost tabhost;private RadioGroup radiogroup;@OverrideimplementsrequestWindowFeature(Window.FEATURE_NO_TITLE); tabhost=getTabHost(); radiogroup.setOnCheckedChangeListener(this); radiogroup.setClickable(true);tabhost.addTab(tabhost.newTabSpec("local_music").setIndicator("local_musi c").setContent(new Intent(this,MusicListActivity.class)));tabhost.addTab(tabhost.newTabSpec("my_collect").setIndicator("my_collect" ).setContent(new Intent(this,CollectionActivity.class)));tabhost.addTab(tabhost.newTabSpec("net_music").setIndicator("net_music"). setContent(new Intent(this,NetMusicActivity.class)));}@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { tabhost.setCurrentTabByTag("local_music");break; tabhost.setCurrentTabByTag("my_collect"); break; tabhost.setCurrentTabByTag("net_music"); break;}}}MusicListActivity.javapublic class MusicListActivity extends Activity {/** 音乐列表 **/private LayoutParams params; private Toast toast; // 提示 public static final int Ringtone = 0; public static final int Alarm = 1; public static final int Notification = 2; private TextView timers;// 显示倒计时的文字 public MusicListAdapter adapter; @Overrideprivate ListView listview; private String musicpath; private int _ids[]; // private String _titles[]; // private String _artists[]; // private String[] _path; // private String[] _times; // private String[] _album; // private int _sizes[]; // private String[] _displayname;// private int num; //num private LayoutInflater inflater;//存放音乐文件的 id 数组 存放音乐文件的标题数组 存放音乐艺术家的标题数组 存放音乐路过的标题数组 存放总时间的标题数组 存放专辑的标题数组 存放文件大小的标题数组 存放名称的标题数组确定一个标识 装载布局/** 选择子项点击事件***/ listview.setOnItemClickListener(new MusicListOnClickListener());listview.setOnCreateContextMenuListener(newMusicListContextListener());inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);params = newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);ShowMp3List();}/**显示MP3信息,其中」ds保存了所有音乐文件的_ID,用来确定到底要播放哪一首歌曲,_titles 存放音乐名,用来显示在播放界面,_path 存放音乐文件的路径(删除文件时会用到) 。

相关主题