这两天刚学完了contentprovider和service组件,就综合下所学的,自制了一个简单的音乐播放器。

代码如下:

主activity代码

public class MainActivity extends Activity implements View.OnClickListener,ServiceConnection{private TextView musicName, musicTime;//歌曲名,歌曲时间private SeekBar seekBar;//歌曲进度private ListView musicList;//歌单private List<HashMap<String, Object>> list;//数据源private Intent intent;//开启服务的意图private int item=0;//当前的itemprivate MusicService.MyBinder binder;//绑定服务返回的一个binder对象private boolean isStart=false;//判断播放器是否在运行private static int state=1;//seekbar的一种状态private Button btn;//获得开始按钮的实例@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();//歌单适配数据,设置item点击监听,绑定服务并且发送数据给handlermusicList.setAdapter(new MyAdapter(list,this));musicList.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {messToServer(position,1);item=position;sendItem(item,1);isStart=true;btn.setText("暂停");}});//设置seekbar监听;seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {
//                sendState(0);state=0;//seekbar按下时的状态避免通过接口回调设置seekbar的进度冲突}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {Log.e("aaa",seekBar.getProgress()+"");binder.setSeekbarTo(seekBar.getProgress());//传递松开时的seekbar的进度messToServer(item,6);
//                sendState(1);state=1;//松开时的状态}});}//实例化控件初始化数据private void init() {findViewById(R.id.musicUp).setOnClickListener(this);btn= (Button) findViewById(R.id.musicStart);btn.setOnClickListener(this);findViewById(R.id.musicStop).setOnClickListener(this);findViewById(R.id.musicDwon).setOnClickListener(this);seekBar = (SeekBar) findViewById(R.id.seekBar);musicName = (TextView) findViewById(R.id.musicName);musicTime = (TextView) findViewById(R.id.musicTime);musicList = (ListView) findViewById(R.id.musicList);list = new ArrayList<>();//获取音频文件的uriUri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;String[] projection = {MediaStore.Audio.Media.DATA,MediaStore.Audio.Media.DISPLAY_NAME};//通过uri查询的路劲和文件名Cursor cursor = getContentResolver().query(uri, projection, null, null, null);//遍历返回的cursor获取数据源while (cursor.moveToNext()){HashMap<String,Object> map=new HashMap<>();map.put("path",cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)));map.put("name",cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)));list.add(map);}//绑定服务intent=new Intent(this,MusicService.class);bindService(intent,this, Context.BIND_AUTO_CREATE);}@Overridepublic void onClick(View v) {switch (v.getId()){//上一曲case R.id.musicUp:item=(item==0)?(list.size()-1):(item-1);sendItem(item,1);messToServer(item,2);break;//开始/暂停case R.id.musicStart:if(isStart){messToServer(item,4);isStart=false;btn.setText("开始");}else{messToServer(item,3);isStart=true;btn.setText("暂停");}sendItem(item,1);break;//停止case R.id.musicStop:isStart=false;sendItem(item,1);messToServer(item,5);btn.setText("开始");break;//下一曲case R.id.musicDwon:item=(item==list.size()-1)?(0):(item+1);sendItem(item,1);messToServer(item,2);break;}}//绑定服务封装public void messToServer(int item,int what){String path=list.get(item).get("path").toString();binder.setPath(path,what);}//实现接口获得从服务器返回的数据,接口回调获得播放器当前的进度和当前歌曲的总时间@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {binder= (MusicService.MyBinder) service;//绑定服务返回的对象//使用接口回调获得播放器的状态,当前进度和总体时间binder.getService().setCallBack(new MusicService.CallBack() {@Overridepublic void onPlayerState(int state, int progress, int duration) {sendProgress(progress,duration,2);
//                sendState(state,3);}});}@Overridepublic void onServiceDisconnected(ComponentName name) {}//创建一个handler,通过what来执行对应操作Handler handler=new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what){case 1://设置当前歌曲的名字int item=msg.getData().getInt("item");musicName.setText(list.get(item).get("name").toString());break;case 2://设置seekbar的最大值和当前进度
//                    int state=msg.getData().getInt("state");//如果seekbar的状态为0则不会按回调的数据来设置progress进度避免了冲突if(state==0){break;}int progress=msg.getData().getInt("progress");int duration=msg.getData().getInt("duration");if(duration<0||durantion<999999){//播放器没播放或者停止的时候分别返回一个很大的数和一个很小的负数progress=0;duration=0;}seekBar.setMax(duration);seekBar.setProgress(progress);//把progress和duration转化成分钟和秒数String dtime=(progress/1000)/60+":"+(progress/1000)%60;String ztime=(duration/1000)/60+":"+(duration/1000)%60;musicTime.setText(dtime+"/"+ztime);break;}}};//发送歌曲name到handler的方法public void sendItem(int item,int what){Message mess=new Message();mess.what=what;Bundle bundle=new Bundle();bundle.putInt("item",item);mess.setData(bundle);handler.sendMessage(mess);}//发送当前进度和总体进度到hander的方法public void sendProgress(int progress,int duration,int what){Message mess=new Message();mess.what=what;Bundle bundle=new Bundle();bundle.putInt("progress",progress);bundle.putInt("duration",duration);mess.setData(bundle);handler.sendMessage(mess);}
//    public void sendState(int state,int what){
//        Message mess=new Message();
//        mess.what=what;
//        Bundle bundle=new Bundle();
//        bundle.putInt("state",state);
//        mess.setData(bundle);
//        handler.sendMessage(mess);
//    }//退出activity停止服务@Overrideprotected void onDestroy() {super.onDestroy();unbindService(this);}
}

service代码

public class MusicService extends Service {private MediaPlayer player;private String path;//从activity获得的pathprivate int what;//从activity获得的动作private boolean isPause = false;//判断是否是暂停private boolean flag = false;//关闭子线程用private CallBack callBack;//一个回调接口private boolean isStop=false;//判断是否停止private boolean first=true;//判断是否第一次执行private int progress=0;//拖动seekbar时返给progress值@Overridepublic void onCreate() {super.onCreate();//实例化mediaplayerplayer = new MediaPlayer();player.setLooping(true);//开启一个子线程来对从activity获得的值操作new Thread(new Runnable() {@Overridepublic void run() {flag = true;while (flag) {switch (what) {case 1://点击listview的item传来path进行播放if (isPause == true) {isPause = false;}startPlayer(path);what = 0;break;case 2://上一曲或者下一曲传来path进行播放,如果播放器没有播放,则什么都不干if (isPause == true) {isPause = false;}if (player.isPlaying()) {startPlayer(path);}else{player.reset();}what = 0;break;//开始播放或者继续播放case 3:startPlayer(path);what = 0;break;//暂停case 4:if(isStop==true){what=3;isStop=false;break;}pausePlayer();what = 0;break;//停止case 5:stopPlayer();what = 0;break;//随着seekbar改变进度case 6:seekBarTo(progress);what=0;break;default:break;}//实现接口if (callBack != null) {if(first==true||isStop==true){callBack.onPlayerState(-1,0,0);isStop=false;first=false;continue;}if (player.isPlaying()) {callBack.onPlayerState(1, player.getCurrentPosition(), player.getDuration());} else {callBack.onPlayerState(0, player.getCurrentPosition(), player.getDuration());}}}}}).start();}@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}public class MyBinder extends Binder {//从activity拿到path和what值public void setPath(String path, int what) {MusicService.this.path = path;MusicService.this.what = what;}//拿到seekbar拖动到的位置值public void setSeekbarTo(int progress){MusicService.this.progress=progress;}//返回一个service的实例public MusicService getService() {return MusicService.this;}}@Overridepublic boolean onUnbind(Intent intent) {return super.onUnbind(intent);}@Overridepublic void onDestroy() {super.onDestroy();//服务关闭的时候关闭线程关闭player并释放资源flag = false;player.stop();player.release();}//开始播放歌曲public void startPlayer(String path) {//如果是暂停状态,则继续播放isStop=false;if (isPause) {player.start();isPause = false;return;}//如果player在运行,则重置playerif (player.isPlaying()) {player.stop();player.reset();}try {player.setDataSource(path);player.prepare();player.start();} catch (IOException e) {e.printStackTrace();}}//暂停播放器public void pausePlayer() {if (player.isPlaying()) {player.pause();isPause = true;}}//停止播放器public void stopPlayer() {player.stop();player.reset();isStop=true;isPause=false;}//从seekbar拖动的位置开始播放private void seekBarTo(int progress) {player.seekTo(progress);player.start();}//接口public interface CallBack {void onPlayerState(int state, int progress, int duration);}public CallBack getCallBack() {return callBack;}public void setCallBack(CallBack callBack) {this.callBack = callBack;}
}
适配器代码
public class MyAdapter extends BaseAdapter {private List<HashMap<String,Object>> list;private Context context;public MyAdapter(List<HashMap<String, Object>> list, Context context) {this.list = list;this.context = context;}@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int position) {return list.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {Holder holder=null;if(convertView==null){convertView=View.inflate(context,R.layout.itemlayout,null);holder=new Holder();holder.listItem= (TextView) convertView.findViewById(R.id.listItem);convertView.setTag(holder);}else{holder= (Holder) convertView.getTag();}holder.listItem.setText(list.get(position).get("name").toString());return convertView;}class Holder{TextView listItem;}
}
主activity的布局文件
<?xml version="1.0" encoding="utf-8"?>
<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"><SeekBarandroid:id="@+id/seekBar"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="30dp" /><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="30dp"android:gravity="center_vertical"><TextViewandroid:lines="1"android:id="@+id/musicName"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:layout_marginRight="50dp"android:textSize="18sp" /><TextViewandroid:id="@+id/musicTime"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginRight="10dp" /></RelativeLayout><LinearLayoutandroid:orientation="horizontal"android:gravity="center"android:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:layout_margin="10dp"android:background="@drawable/button"android:id="@+id/musicUp"android:text="上曲"android:layout_width="60dp"android:layout_height="40dp" /><Buttonandroid:layout_margin="10dp"android:background="@drawable/button"android:id="@+id/musicStart"android:text="开始"android:layout_width="60dp"android:layout_height="40dp" /><Buttonandroid:layout_margin="10dp"android:background="@drawable/button"android:id="@+id/musicStop"android:text="停止"android:layout_width="60dp"android:layout_height="40dp" /><Buttonandroid:layout_margin="10dp"android:id="@+id/musicDwon"android:background="@drawable/button"android:text="下曲"android:layout_width="60dp"android:layout_height="40dp" /></LinearLayout><TextViewandroid:gravity="center"android:text="我的歌单"android:textSize="20sp"android:layout_width="match_parent"android:layout_height="wrap_content" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><ListViewandroid:layout_marginTop="10dp"android:id="@+id/musicList"android:layout_width="match_parent"android:layout_height="match_parent"></ListView></LinearLayout></LinearLayout>
ListView的item布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_margin="5dp"android:textSize="15sp"android:id="@+id/listItem"android:lines="1"android:layout_width="wrap_content"android:layout_height="wrap_content" />
</LinearLayout>
以上就是实现过程

自制一个简单的音乐播放器相关推荐

  1. 用Qt写一个简单的音乐播放器(三):增加界面(播放跳转与音量控制)

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  2. 用Qt写一个简单的音乐播放器(六):显示歌词(正则表达式)

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  3. 用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐

    一.前言 QMediaplayer可以用于解析音频文件和视频文件,继承自QMediaObject,涉及到的对象为QMediaContent.QMediaObject可以提供关于媒体内容的接入,通过UR ...

  4. 用Qt写一个简单的音乐播放器(五):歌曲播放时间显示

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  5. Android开发做一个简单的音乐播放器

    Android开发如何做一个简单的音乐播放器,首先我们先要知道用到的知识点有哪些. 1.MediaPlayer:可以播放本地资源.sd卡内存资源以及网络uri资源,在这里我们播放sd卡上的音乐资源. ...

  6. 用Qt写一个简单的音乐播放器(七):界面美化(QSS样式表)

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  7. 用Qt写一个简单的音乐播放器(四):歌曲浏览、上一曲、下一曲

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  8. Android 一个简单的音乐播放器

    前言: 这次算是第三次自己做音乐播放器了,一次比一次进步一些啦.不过感觉还是太简陋了,哈哈.技术差... 效果图: 电脑配置比较差,所以模拟器有些卡,效果图也看到有些卡顿. App主要就是分两部分:数 ...

  9. 用C/C++写一个简单的音乐播放器(基于windows控制台编程)

    学习内容:1. 使用单例模式设计,让加载资源唯一化. 2. 控件管理. 3. 按键消息处理 4. 音频函数的使用 1. 资源管理与加载 1.1 公共头文件 将用到的头文件保存到一个公共头文件" ...

最新文章

  1. Jscript 随记
  2. override java field_JavaPoet 看这一篇就够了
  3. AngularJS——第3章 指令
  4. parse_str与http_build_query的使用
  5. Linux Kernel 4.20 生命周期已结束,建议迁移 5.0
  6. MySQL高级 - 常用工具 - mysqlshow
  7. 程序员每天该做的事情
  8. java ajax多文件上传插件_ajaxFileUpload.js插件支持多文件上传的方法
  9. python2精确除法
  10. acer软件保护卡怎么解除_Acer软件保护卡使用说明全解.doc
  11. 安装python失败的方法_安装python不失败的方法
  12. js、css基础总结
  13. 小米开发版安装magisk_MIUI10开发版/安卓P完美xposed与magisk框架教程
  14. android app文件夹,android app文件目录结构
  15. Python绘制气泡图
  16. 2022帆软BI数据分析大赛强势来袭,瓜分20W奖金
  17. 分布式数据库如何实现主键全局自增?
  18. Matlab:如何批量修改图片名称(图像处理)
  19. NLTK11《Python自然语言处理》code10 分析语句的含义
  20. 如何在iphone/ipad/itouch上设置新浪VIP邮箱

热门文章

  1. Unity 中用 Vertex Fragment Shader 实现 surface shader 中的 Diffuse 和 Decal
  2. Db2插入数据溢出报错测试
  3. 【Spring源码】ClassPathResource 资源文件源码分析
  4. 哪个品牌的触控笔质量好?ipad好用的触控笔
  5. Downloading from maven-public: http:///maven-metadata.xml卡住了
  6. 注册kaggle帐号及kaggle绑定手机收不到验证码的问题
  7. 关于谷歌邮箱注册收不到验证码——”此电话号码无法用于验证“的问题
  8. 十一、Spring Boot整合Redis(一)
  9. php获取用户访问的dns,dnsproxy in php
  10. 考试计算机输百分比符号,2012年计算机等级考试一级B考点详解(4)