如何用visual basic制作自己的易语言制作音乐播放器器

您的举报已经提交成功,我们将尽快处理,谢谢!
论强大当然是c了,但是c偏向底层,以简小精炼著称,很多程序需要用到已有的功能需要庞大的函数库支持,这一点c就不行了。因此说,c理论上无所不能,但是只有在底层编程...
大家还关注音乐播放器的实现,框架的基本搭建,资源 - 博客频道 - CSDN.NET
丿灬安之若死
来啊,一起学习啊
分类:android技术
你们肯定会说没图我怎么做...那好吧 我压缩一下藏在百度云把是整体的所有图片哦 有的可能用不到
链接:/s/1mhOXk4g 密码:7t92有的人肯定比我还懒 &我就想要个apk 或者我就想要个项目 好吧 你赢了 我给你地址 我用的开发工具是androidStudio
链接:/s/1pLbIjMV 密码:55in
他是从vbFragmen里面跳进去的 所以 得从Main说起 我把完整的项目结构拷贝进来了 然后就实现音乐
我把重要的类写出来 &如果想看全部的话 可以下载上面有地址
MainActivity
播放音乐的界面
MusicPlayerActivity
package com.example.liuan.phonevideo.
import android.content.BroadcastR
import ponentN
import android.content.C
import android.content.I
import android.content.IntentF
import android.content.ServiceC
import android.graphics.C
import android.graphics.drawable.AnimationD
import android.os.B
import android.os.B
import android.os.E
import android.os.H
import android.os.IB
import android.os.M
import android.support.v7.app.AppCompatA
import android.view.V
import android.view.W
import android.view.WindowM
import android.widget.ImageV
import android.widget.LinearL
import android.widget.RelativeL
import android.widget.SeekB
import android.widget.TextV
import com.example.liuan.phonevideo.R;
import com.example.liuan.phonevideo.bean.MusicI
import com.example.liuan.phonevideo.lyic.LyncV
import com.example.liuan.phonevideo.service.MusicPlayerS
import com.example.liuan.phonevideo.utils.U
import java.io.F
import butterknife.B
import butterknife.ButterK
import butterknife.OnC
public class MusicPlayerActivity extends AppCompatActivity {
@Bind(R.id.iv_back)
ImageView ivB
@Bind(R.id.tv_title)
TextView tvT
@Bind(R.id.tv_artist)
TextView tvA
@Bind(R.id.rl_top)
RelativeLayout rlT
@Bind(R.id.iv_wave)
ImageView ivW
@Bind(R.id.tv_time)
TextView tvT
@Bind(R.id.sb_progress)
SeekBar sbP
@Bind(R.id.iv_playmode)
ImageView ivP
@Bind(R.id.iv_pre)
ImageView ivP
@Bind(R.id.iv_play_pause)
ImageView ivPlayP
@Bind(R.id.iv_next)
ImageView ivN
@Bind(R.id.iv_list)
ImageView ivL
@Bind(R.id.lic_view)
LyncView mLyricV
private MusicPlayerService.MusicC
private String totalT
private MyServiceConnection serviceC
private AnimationD
private MyR
private static final int UPDATA_PLAYED_TIME = 1;
private static final int UPDATE_LYRIC = 2;
public Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATA_PLAYED_TIME:
updataPlayedTime();
case UPDATE_LYRIC:
updatalyric();
private void updatalyric() {
mLyricView.updateLyrics(music.getCurrentPosition(), music.getDuration());
handler.sendEmptyMessageDelayed(UPDATE_LYRIC, 100);
private void updataPlayedTime() {
//获取当前播放的位置
int currentPosition = music.getCurrentPosition();
String time = Utils.formatPlayTime(currentPosition);
tvTime.setText(time + &/& + totalTime);
//跟新进度条进度
sbProgress.setProgress(currentPosition);
//通过hanller
//半秒后 再次执行这个方法
handler.sendEmptyMessageDelayed(UPDATA_PLAYED_TIME, 500);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//沉浸状态栏
if (Build.VERSION.SDK_INT &= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
window.setNavigationBarColor(Color.TRANSPARENT);
setContentView(R.layout.activity_music_player);
ButterKnife.bind(this);
initService();
initView();
receiver = new MyReceiver();
IntentFilter filter = new IntentFilter(&com.example.startPlay&);
filter.addAction(&com.example.stopPlay&);
registerReceiver(receiver, filter);
private void initService() {
Intent intent = getIntent();
intent.setClass(getApplicationContext(), MusicPlayerService.class);
startService(intent);//会执行 onCreate onStatrtCommand*(会多次执行)
//混合方式开启服务
serviceConnection = new MyServiceConnection();
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
private void initView() {
* 获取状态栏高度
int statusBarHeight1 = -1;
//获取status_bar_height资源的ID
int resourceId = getResources().getIdentifier(&status_bar_height&, &dimen&, &android&);
if (resourceId & 0) {
//根据资源ID获取响应的尺寸值
statusBarHeight1 = getResources().getDimensionPixelSize(resourceId);
//获取状态栏高度 设置到顶部标题栏的顶部外边距
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) rlTop.getLayoutParams();
layoutParams.topMargin = statusBarHeight1;
rlTop.setLayoutParams(layoutParams);
//开启动画
animation = (AnimationDrawable) ivWave.getDrawable();
sbProgress.setOnSeekBarChangeListener(new MyOnSeekBarChangeListener());
@OnClick({R.id.iv_back, R.id.iv_playmode, R.id.iv_pre, R.id.iv_play_pause, R.id.iv_next, R.id.iv_list})
public void onClick(View view) {
switch (view.getId()) {
case R.id.iv_playmode:
MusicPlayerService.currenMode = ++MusicPlayerService.currenMode % 3;
updataPlayModeIcon();
getSharedPreferences(&music_config&, MODE_PRIVATE).edit().putInt(&playmode&, MusicPlayerService.currenMode).commit();
case R.id.iv_pre:
music.preNext(MusicPlayerService.PLAY_PRE);
case R.id.iv_play_pause:
music.palyPause();
updatePlayPanseIcon();
case R.id.iv_next:
music.preNext(MusicPlayerService.PLAY_NEXT);
case R.id.iv_list:
case R.id.iv_back:
private void updataPlayModeIcon() {
switch (MusicPlayerService.currenMode) {
case MusicPlayerService.PLAY_MODE_LIST:
ivPlaymode.setImageResource(R.drawable.selector_playmode_list);
case MusicPlayerService.PLAY_MODE_SINGLE:
ivPlaymode.setImageResource(R.drawable.selector_playmode_single);
case MusicPlayerService.PLAY_MODE_SHUFFLE:
ivPlaymode.setImageResource(R.drawable.selector_playmode_shuffle);
private class MyOnSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//用户操作
if (fromUser) {
music.seekTo(progress);
public void onStartTrackingTouch(SeekBar seekBar) {
//开始操作进度条走这个方法
public void onStopTrackingTouch(SeekBar seekBar) {
//停止操作进度条走这个方法
private class MyServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service) {
//bindService开启 如果onBinde方法有返回值 就会执行这个方法
//第二个参数 IBinder service就是onBind返回值
music = (MusicPlayerService.MusicController)
public void onServiceDisconnected(ComponentName name) {
protected void onStart() {
super.onStart();
if (music != null) {
handler.sendEmptyMessage(UPDATA_PLAYED_TIME);
protected void onStop() {
super.onStop();
handler.removeCallbacksAndMessages(null);
protected void onDestroy() {
super.onDestroy();
//bindService开启服务需要在activity 销毁 解锁绑定
unbindService(serviceConnection);
unregisterReceiver(receiver);
private class MyReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (&com.example.startPlay&.equals(action)) {
initPlayerUI();
updataPlayedTime();
updatePlayPanseIcon();
//加载歌词 解析
//tianhou.MP3
String fileName = music.getCurrentMusic().displayName.split(&\\.&)[0];
File file = new File(Environment.getExternalStorageDirectory() + &/hh&, fileName + &.txt&);
mLyricView.loadLyrice(file);
//更新歌词
updatalyric();
} else if (&com.example.stopPlay&.equals(action)) {
handler.removeMessages(UPDATA_PLAYED_TIME);
//移除所有的消息
handler.removeCallbacksAndMessages(null);
* 初始化播放界面
private void initPlayerUI() {
MusicItem currentMusic = music.getCurrentMusic();
tvTitle.setText(currentMusic.title);
tvArtist.setText(currentMusic.artist);
//更新播放的图标
updatePlayPanseIcon();
//更新播放的总时长
totalTime = Utils.formatPlayTime(currentMusic.duration);
tvTime.setText(&00:00/& + totalTime);
//初始化 seekbar的总时长
sbProgress.setMax(currentMusic.duration);
private void updatePlayPanseIcon() {
if (music.isPlaying()) {
ivPlayPause.setImageResource(R.drawable.selector_play);
animation.start();
ivPlayPause.setImageResource(R.drawable.selector_pause);
animation.stop();
初始化listView数据的adapter继承了cursoradapter
MusicAdapter
package com.example.liuan.phonevideo.
import android.content.C
import android.database.C
import android.provider.MediaS
import android.support.v4.widget.CursorA
import android.text.format.F
import android.view.LayoutI
import android.view.V
import android.view.ViewG
import android.widget.TextV
import com.example.liuan.phonevideo.R;
* Name: MusicAdapter
* Author: liuan
* creatTime: 11:39
public class MusicAdapter extends CursorAdapter {
//不推荐第三个参数是boolean 如果第三个传入true当Currsor发生改变 会自动调用requery刷新界面
public MusicAdapter(Context context, Cursor c) {
//参3 注册内容观察者来处理游标变化的操作
super(context, c, FLAG_REGISTER_CONTENT_OBSERVER);
public View newView(Context context, Cursor cursor, ViewGroup parent) {
//创建新的布局
View inflate = LayoutInflater.from(context).inflate(R.layout.item_music, parent, false);
ViewHolder viewHolder = new ViewHolder(inflate);
inflate.setTag(viewHolder);
public void bindView(View view, Context context, Cursor cursor) {
//给条目设置数据 通过这个bindVIew
ViewHolder holder= (ViewHolder) view.getTag();
title = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
String titleString = cursor.getString(title);
holder.tv_title.setText(titleString);
holder.tv_artist.setText(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)));
long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE));
String sizeString = Formatter.formatFileSize(context, size);
if(titleString.contains(&-&)){
holder.tv_title.setText(titleString.split(&-&)[0]);
holder.tv_artist.setText(titleString.split(&-&)[1]);
holder.tv_size.setText(sizeString);
class ViewHolder{
TextView tv_
TextView tv_
TextView tv_
public ViewHolder(View view) {
tv_title = (TextView) view.findViewById(R.id.tv_title);
tv_artist = (TextView) view.findViewById(R.id.tv_artist);
tv_size = (TextView) view.findViewById(R.id.tv_size);
超级简单的Fragment的封装
BaseFragment
一般有集合的地方 就有数据bean
歌词的数据bean
package com.example.liuan.phonevideo.
* Name: Lyric
* Author: liuan
* creatTime: 10:51
public class Lyric implements Comparable&Lyric& {
* 一行歌词的文字
* 当前行歌词开始演唱的时刻
public Lyric(String text, int time) {
this.text =
this.time =
public int compareTo(Lyric o) {
return this.time-o.
音乐条目的数据bean
package com.example.liuan.phonevideo.
import android.database.C
import android.provider.MediaS
import java.io.S
* Name: MusicItem
* Author: liuan
* creatTime: 14:53
public class MusicItem implements Serializable{
public String displayN
public static MusicItem getMusicFromCursor(Cursor cursor){
if(cursor==null){
MusicItem musicItem = new MusicItem();
musicItem.data=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
musicItem.title=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
musicItem.artist=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
musicItem.size=cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE));
musicItem.duration=cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
if(musicItem.title.contains(&-&)){
musicItem.artist= musicItem.title.split(&-&)[0].trim();
musicItem.title= musicItem.title.split(&-&)[1].trim();
musicItem.displayName=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
return musicI
如果音乐列表太大的话 会阻塞主线程 一般不会用的是数据库 解决方案
MyAsyncQueryHandler
package com.example.liuan.phonevideo.
import android.content.AsyncQueryH
import android.content.ContentR
import android.database.C
import com.example.liuan.phonevideo.adapter.MusicA
* Name: MyAsyncQueryHandler
* Author: liuan
* creatTime: 14:45
public class MyAsyncQueryHandler extends AsyncQueryHandler {
public MyAsyncQueryHandler(ContentResolver cr) {
super(cr);
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
super.onQueryComplete(token, cookie, cursor);
MusicAdapter adapter = (MusicAdapter)
//替换旧的游标 如果旧的游标不为空 会关闭
adapter.changeCursor(cursor);
//替换旧的游标 把旧的游标作为返回值 返回 不会关闭
adapter.swapCursor(cursor);
音乐列表的实现
VbangFragment
package com.example.liuan.phonevideo.
import android.M
import android.content.ContentR
import android.content.I
import android.database.C
import android.net.U
import android.os.B
import android.provider.MediaStore.Audio.M
import android.support.v4.app.ActivityC
import android.support.v4.content.PermissionC
import android.view.V
import android.widget.AdapterV
import android.widget.ListV
import com.example.liuan.phonevideo.R;
import com.example.liuan.phonevideo.activity.MusicPlayerA
import com.example.liuan.phonevideo.adapter.MusicA
import com.example.liuan.phonevideo.base.BaseF
import com.example.liuan.phonevideo.bean.MusicI
import com.example.liuan.phonevideo.db.MyAsyncQueryH
import java.util.ArrayL
import butterknife.B
* Name: MainFragment
* Author: liuan
* creatTime: 10:25
public class VbangFragment extends BaseFragment {
@Bind(R.id.lv_vbang)
ListView lvV
private MusicA
protected int getLayoutId() {
return R.layout.fragment_
protected void initView(View view) {
adapter = new MusicAdapter(getContext(), null);
lvVbang.setAdapter(adapter);
lvVbang.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView&?& parent, View view, int position, long id) {
ArrayList&MusicItem& musics=new ArrayList&MusicItem&();
Cursor cursor = adapter.getCursor();
if(cursor!=null){
cursor.moveToPosition(-1);
while (cursor.moveToNext()){
musics.add(MusicItem.getMusicFromCursor(cursor));
Intent intent = new Intent(getContext(), MusicPlayerActivity.class);
intent.putExtra(&musics&,musics);
intent.putExtra(&position&,position);
System.out.println(&zou &+musics.get(position));
startActivity(intent);
System.out.println(&zou &);
//如果版本》23
if (Build.VERSION.SDK_INT &= 23) {
//参1 检测当前应用是否有特定权限
//参2 需要检测权限 维系那权限 才需要动态申请
// 危险权限 跟用户隐私相关的权限 sd卡 短信 通话记录 打带你话 位置 摄像头 录音机
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) == PermissionChecker.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
initData();
public void initData() {
AsyncQueryHandler asyncQueryHandler
//内容解析者
ContentResolver contentResolver = getActivity().getContentResolver();
Uri uri = Media.EXTERNAL_CONTENT_URI;
Cursor cursor = contentResolver.query(uri, new String[]{
Media._ID,
Media.DATA,//文件路径
Media.DURATION,//时长
Media.SIZE,
Media.TITLE, Media.ARTIST
},null, null, null);
Utils.printCUrrsor(cursor);
MyAsyncQueryHandler queryHandler = new MyAsyncQueryHandler(contentResolver);
//参1 异步查询 如果有不同查询 用来区分不同查询
//第二参数 cookie可以传任意对象给onQUeCO
queryHandler.startQuery(1,adapter,uri, new String[]{
Media._ID,
Media.DATA,//文件路径
Media.DURATION,//时长
Media.SIZE,
Media.TITLE,
Media.ARTIST,
Media.DISPLAY_NAME
},null, null, null);
自定义歌词view继承TextView不用写onMeasure方法
package com.example.liuan.phonevideo.
import android.content.C
import android.graphics.C
import android.graphics.C
import android.graphics.LinearG
import android.graphics.P
import android.graphics.R
import android.graphics.S
import android.os.B
import android.support.annotation.RequiresA
import android.util.AttributeS
import android.widget.TextV
import com.example.liuan.phonevideo.R;
import com.example.liuan.phonevideo.bean.L
import java.io.F
import java.util.ArrayL
* Name: LyncView
* Author: liuan
* creatTime: 10:16
public class LyncView extends TextView {
private int viewH
private int viewW
//正在播放的歌词文字大小
private float bigFongS
//普通歌词文字大小
private float normalFongS
//行高 每一行的行高
private float lineH
private ArrayList&Lyric& lyrices=new ArrayList&&();
//正在演唱的歌词 在歌词集合索引中
private int currentIndex = 5;
private int heightLightC
private int currentT
private float passedP
private int centerY;
public LyncView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
public LyncView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initParams();
private void initParams() {
bigFongSize = getResources().getDimension(R.dimen.bigFontSize);
normalFongSize = getResources().getDimension(R.dimen.normalFongSize);
lineHeight = getResources().getDimension(R.dimen.lineHeight);
heightLightColor = getResources().getColor(R.color.colorMusicProgress);
paint = new Paint();
paint.setAntiAlias(true);
//矩形对象 用来测量文字边界
bounds = new Rect();
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public LyncView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (lyrices != null && lyrices.size() & 0) {
canvas.translate(0, -getTransY());
drawAllText(canvas);
private float getTransY() {
if (currentIndex == lyrices.size() - 1) {
//最后一句
//当前歌词开始演唱的时刻
int startTime = lyrices.get(currentIndex).
//这一行应该演唱的总时长 用歌曲的总时长-最后一行歌词开始唱
int totalTime = duration - startT
//这一行歌词已经演唱了多久
int passedTime = currentTime - startT
//当时时刻应该移动的距离
return lineHeight * passedTime / totalT
//当歌词开始演唱的时刻
int startTime = lyrices.get(currentIndex).
//这一行应该演唱的总时长
int totalTime = lyrices.get(currentIndex + 1).time - startT
//这一行歌词已经演唱了多久
int passedTime=currentTime-startT
passedPercent = passedTime / (float) totalT
//当时时刻应该移动的距离
return lineHeight * passedTime / totalT
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//获取到view的宽度和高度
viewHeight =
viewWidth =
String text=&我是一行歌词歌词&;
paint.setTextSize(bigFongSize);
paint.getTextBounds(text,0,text.length(),bounds);
//确定屏幕中间的y坐标的位置
centerY = viewHeight / 2 + bounds.height() / 2;
* 根据当前歌词的索引 以及正在演唱的歌词索引currentPosition 来绘制一行歌词
* @param index 当前歌词在集合中的索引
* @param canvas
private void drawSingleLyric(int index, Canvas canvas) {
//通过索引获取到这一行歌词
String text = lyrices.get(index).
//判断当前的索引和正在演唱的歌词索引 是否相同
if (index == currentIndex) {
//正在演唱的歌词
paint.setTextSize(bigFongSize);
paint.setColor(heightLightColor);
paint.getTextBounds(text,0,text.length(),bounds);
int textWidth = bounds.width();
float x=viewWidth/2-textWidth/2;
paint.setShader(new LinearGradient(x,centerY,x+textWidth,centerY,
new int[]{heightLightColor, Color.WHITE},
new float[]{passedPercent,passedPercent+0.01f},
Shader.TileMode.CLAMP));
paint.setTextSize(normalFongSize);
paint.setColor(Color.WHITE);
paint.setShader(null);
//测量文字的边界
paint.getTextBounds(text,0,text.length(),bounds);
int textWidth=bounds.width();
float x=viewWidth/2-textWidth/2;
// y坐标 中间位置+当前行和正在唱的行号差距*行高
float y=centerY+(index-currentIndex)*lineH
canvas.drawText(text,x,y,paint);
遍历结合 绘制集合中的所有歌词
private void drawAllText(Canvas canvas) {
for (int i = 0; i & lyrices.size(); i++) {
drawSingleLyric(i, canvas);
* 更新正在演唱的时刻 更新正在唱的歌词索引
* @param currentTime
public void updateCurrentIndex(int currentTime) {
for (int i = 0; i & lyrices.size(); i++) {
if (i == lyrices.size() - 1) {
currentIndex =
//当前行的时刻小于正在播放的时刻 并且下一行的时刻 大于正在播放的时刻
if (lyrices.get(i).time & currentTime && lyrices.get(i + 1).time & currentTime) {
//这行歌词正在演唱
currentIndex =
public void updateLyrics(int currentTime,int duration){
this.currentTime=currentT
this.duration=
//更新正在唱的歌词索引
updateCurrentIndex(currentTime);
//重新绘制界面
invalidate();
public void loadLyrice(File file) {
解析歌词保存到lyrics这个集合
lyrices=LyricsParser.parserFromFile(file);
歌词的解析类
LyricsParser
package com.example.liuan.phonevideo.
import com.example.liuan.phonevideo.bean.L
import java.io.BufferedR
import java.io.F
import java.io.FileInputS
import java.io.FileNotFoundE
import java.io.IOE
import java.io.InputStreamR
import java.io.UnsupportedEncodingE
import java.util.ArrayL
import java.util.C
import java.util.L
* Name: LyricsParser
* Author: liuan
* creatTime: 20:26
public class LyricsParser
* 从歌词文件解析出歌词数据列表
public static ArrayList&Lyric& parserFromFile(File lyricsFile) {
ArrayList&Lyric& lyricsList = new ArrayList&&();
// 数据可用性检查
if (lyricsFile == null || !lyricsFile.exists()) {
lyricsList.add(new Lyric(&没有找到歌词文件。&,0));
return lyricsL
// 按行解析歌词
BufferedReader buffer = new BufferedReader(new InputStreamReader(new FileInputStream(lyricsFile),&GBK&));
String line
= buffer.readLine();
while (line!=null){
List&Lyric& lineList = parserLine(line);
lyricsList.addAll(lineList);
line = buffer.readLine();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
// 歌词排序
如果歌词是这种格式的[01:45.51][02:58.62]整理好心情再出发
//如果解析之后不排序 歌词的顺序是乱的 sort方法 需要javabean 实现comparable接口 重写compareTo方法
//返回负数排在前面
Collections.sort(lyricsList);
return lyricsL
private static List&Lyric& parserLine(String line) {
ArrayList&Lyric& lineList = new ArrayList&&();
[01:45.51][02:58.62 整理好心情再出发
String[] arr = line.split(&]&);
String content = arr[arr.length - 1];
//[01:45.51][02:58.62
for (int i = 0; i & arr.length - 1; i++) {
int startPoint = parserStartPoint(arr[i]);
lineList.add(new Lyric(content, startPoint));
return lineL
private static int parserStartPoint(String startPoint) {
int time = 0;
String[] arr = startPoint.split(&:&);
String minStr = arr[0].substring(1);
arr = arr[1].split(&\\.&);
String secStr = arr[0];
String mSecStr = arr[1];
time = Integer.parseInt(minStr) * 60 * 1000
+Integer.parseInt(secStr) * 1000
+Integer.parseInt(mSecStr) * 10;
音乐就算返回了也可以播放 所以要写在服务中
MusicPlayerService
package com.example.liuan.phonevideo.
import android.app.N
import android.app.NotificationM
import android.app.PendingI
import android.app.S
import android.content.I
import android.media.MediaP
import android.os.B
import android.os.B
import android.os.IB
import android.support.annotation.N
import android.support.v4.app.NotificationC
import android.widget.RemoteV
import com.example.liuan.phonevideo.R;
import com.example.liuan.phonevideo.activity.MusicPlayerA
import com.example.liuan.phonevideo.bean.MusicI
import java.io.IOE
import java.util.ArrayL
import java.util.R
* Name: MusicPlayerService
* Author: liuan
* creatTime: 15:53
public class MusicPlayerService extends Service {
private static final int OPEM_ACTIVITY = 3;
private static final int CANCEL_NOTIFICATION =4 ;
private static final int PLAY_PAUSE =5 ;
private MediaPlayer mediaP
private ArrayList&MusicItem&
private int currentPosition = -1;
public static final int PLAY_MODE_LIST = 0;
public static final int PLAY_MODE_SINGLE = 1;
public static final int PLAY_MODE_SHUFFLE = 2;
public static final int PLAY_PRE = 38;
public static final int PLAY_NEXT = 836;
public static int currenMode = 0;
public IBinder onBind(Intent intent) {
// 只执行一次
return new MusicController();
public class MusicController extends Binder {
* 根据当前的播放状态控制音乐的播放和暂停
public void palyPause() {
MusicPlayerService.this.playPause();
* 获取当前正在播放音乐的JavaBean* s
public MusicItem getCurrentMusic() {
return musics.get(currentPosition);
* 获取播放的状态
public boolean isPlaying() {
return mediaPlayer.isPlaying();
* * \获取当前播放了多久
* @return 已经播放时长的毫秒值
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
public void seekTo(int position) {
mediaPlayer.seekTo(position);
public void preNext(int mode) {
MusicPlayerService.this.preNext(mode);
public int getDuration() {
return mediaPlayer.getDuration();
private void stopUpdateUI() {
sendBroadcast(new Intent(&com.example.stopPlay&));
* 根据当前的播放状态控制音乐的播放和暂停
private void playPause() {
//如果处于播放状态就暂停
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
stopUpdateUI();
//如果处于暂停状态 就开始播放
mediaPlayer.start();
notifyPlayerUpdateUI();
private void preNext(int mode) {
//就是根据当前的播放模式来修改 currentposition
//就是正在播放的歌曲在列表中的索引
switch (currenMode) {
case PLAY_MODE_LIST:
if (mode == PLAY_PRE) {
//如果是第一首 移动到列表的最后一首继续播
currentPosition = currentPosition == 0 ? musics.size() - 1 : --currentP
} else if (mode == PLAY_NEXT) {
currentPosition = (++currentPosition) % musics.size();
case PLAY_MODE_SINGLE:
//单曲循环不需要修该播放的索引
case PLAY_MODE_SHUFFLE:
Random random = new Random();
int temp = random.nextInt(musics.size());
while (temp == currentPosition) {
temp = random.nextInt(musics.size());
currentPosition =
//重新播放音乐
startPlay();
public void onCreate() {
super.onCreate();
currenMode = getSharedPreferences(&music_config&, MODE_PRIVATE).getInt(&playmode&, 0);
public int onStartCommand(Intent intent, int flags, int startId) {
//区分这个意图是从通知中来还是从上一个activity中来
boolean fromNotification = intent.getBooleanExtra(&fromNotification&, false);
if (fromNotification) {
int operation = intent.getIntExtra(&operation&, 0);
switch (operation) {
case PLAY_NEXT:
preNext(PLAY_NEXT);
case PLAY_PRE:
preNext(PLAY_PRE);
case OPEM_ACTIVITY:
notifyPlayerUpdateUI();
case CANCEL_NOTIFICATION:
NotificationManager manager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//消除通知
manager.cancel(1);
case PLAY_PAUSE:
playPause();
//更新通知
sendCustomNotification();
//获取所有音乐
musics = (ArrayList&MusicItem&) intent.getSerializableExtra(&musics&);
//获取到了点击当前条目位置
int temp = intent.getIntExtra(&position&, 0);
if (temp == currentPosition) {
//如果点击的条目 跟当前的音乐是同一首
不做音乐播放处理
//通知更新界面
notifyPlayerUpdateUI();
//如果点击的条目 跟当前的音乐不是一首
再重置处理
currentPosition =
//开始准备mediaPlayer
startPlay();
return super.onStartCommand(intent, flags, startId);
private void startPlay() {
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(new MyOnPreparedListerer());
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
//音乐播放结束 自动播放下一首
preNext(PLAY_NEXT);
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
//切换歌曲的操作
//停止UI更新
stopUpdateUI();
//重置mediaplayer
mediaPlayer.reset();
//设置要播放的音乐路径
mediaPlayer.setDataSource(musics.get(currentPosition).data);
//异步准备 准备好了 之后会走setONPreparedListerer
//MyONpreparedListener的onPrepared
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
private class MyOnPreparedListerer implements MediaPlayer.OnPreparedListener {
public void onPrepared(MediaPlayer mp) {
//准备好 之后以后音乐就开始了
mediaPlayer.start();
//通知activity更新界面
notifyPlayerUpdateUI();
sendNomalNotification();
private void notifyPlayerUpdateUI() {
//发送广播 通知activity一月已经开始播放了 可以更新UI
sendBroadcast(new Intent(&com.example.startPlay&));
private void sendNomalNotification() {
//创建通知
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setSmallIcon(R.drawable.music_default_bg);
builder.setContentTitle(musics.get(currentPosition).title);
builder.setContentText(musics.get(currentPosition).artist);
builder.setContentInfo(musics.get(currentPosition).displayName);
//说明是正在进行的通知 不能让用户通过手动操作销毁通知
builder.setOngoing(true);
//点击以后会触发一个PendingIntnetn点击会自动小时一般促销、新闻系哦啊系 一般是antoCancel
builder.setAutoCancel(true);
Notification notification = builder.build();
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(1, notification);
private void sendCustomNotification() {
//创建通知
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setSmallIcon(R.drawable.music_default_bg);
builder.setContent(getRemoteViews());
//android4.1之后支持的
if(Build.VERSION.SDK_INT&=16){
builder.setCustomContentView(getBitRemoteViews());
Notification notification = builder.build();
NotificationManager manager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(1,notification);
private RemoteViews getBitRemoteViews() {
//构造第一个参数 包名===第二个参数 布局的资源id
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_big);
remoteViews.setTextViewText(R.id.tv_notification_title,musics.get(currentPosition).title);
remoteViews.setTextViewText(R.id.tv_notification_artist,musics.get(currentPosition).artist);
if(mediaPlayer.isPlaying()){
//给remoteView设置imageView的资源
remoteViews.setImageViewResource(R.id.iv_notification_playPause,R.drawable.selector_play);
remoteViews.setImageViewResource(R.id.iv_notification_playPause,R.drawable.selector_pause);
//给remoteViews设置点击事件
remoteViews.setOnClickPendingIntent(R.id.iv_notification_pre,getPrePendingIntent());
remoteViews.setOnClickPendingIntent(R.id.iv_notification_next,getNextPendingIntent());
remoteViews.setOnClickPendingIntent(R.id.rl_notification,getActivityPendingIntent());
remoteViews.setOnClickPendingIntent(R.id.iv_notification_playPause,getPlayPausePendingIntent());
remoteViews.setOnClickPendingIntent(R.id.iv_notification_cancel,getCancelPendingIntent());
return remoteV
private PendingIntent getCancelPendingIntent() {
Intent intent = new Intent(getApplicationContext(), MusicPlayerService.class);
intent.putExtra(&fromNotification&,true);
intent.putExtra(&operation,&,CANCEL_NOTIFICATION);
//getService==stringService中的onStaritCOmmand中可以收到这个意图
return PendingIntent.getService(getApplicationContext(),4,intent,PendingIntent.FLAG_UPDATE_CURRENT);
private PendingIntent getPlayPausePendingIntent() {
Intent intent = new Intent(getApplicationContext(), MusicPlayerService.class);
intent.putExtra(&fromNotification&,true);
intent.putExtra(&operation,&,PLAY_PAUSE);
//getService==stringService中的onStaritCOmmand中可以收到这个意图
return PendingIntent.getService(getApplicationContext(),5,intent,PendingIntent.FLAG_UPDATE_CURRENT);
public RemoteViews getRemoteViews() {
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_normal);
remoteViews.setTextViewText(R.id.tv_notification_title,musics.get(currentPosition).title);
remoteViews.setTextViewText(R.id.tv_notification_artist,musics.get(currentPosition).artist);
remoteViews.setOnClickPendingIntent(R.id.iv_notification_pre,getPrePendingIntent());
remoteViews.setOnClickPendingIntent(R.id.iv_notification_next,getNextPendingIntent());
remoteViews.setOnClickPendingIntent(R.id.rl_notification,getActivityPendingIntent());
return remoteV
private PendingIntent getActivityPendingIntent() {
Intent intent = new Intent(getApplicationContext(), MusicPlayerActivity.class);
intent.putExtra(&fromNotification&,true);
intent.putExtra(&operation,&,OPEM_ACTIVITY);
//getService==stringService中的onStaritCOmmand中可以收到这个意图
PendingIntent activity = PendingIntent.getActivity(getApplicationContext(), 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
activity.getBroadcast()
private PendingIntent getNextPendingIntent() {
Intent intent = new Intent(getApplicationContext(), MusicPlayerService.class);
intent.putExtra(&fromNotification&,true);
intent.putExtra(&operation,&,PLAY_NEXT);
//getService==stringService中的onStaritCOmmand中可以收到这个意图
return PendingIntent.getService(getApplicationContext(),3,intent,PendingIntent.FLAG_UPDATE_CURRENT);
private PendingIntent getPrePendingIntent() {
Intent intent = new Intent(getApplicationContext(), MusicPlayerService.class);
intent.putExtra(&fromNotification&,true);
intent.putExtra(&operation,&,PLAY_PRE);
//getService==stringService中的onStaritCOmmand中可以收到这个意图
return PendingIntent.getService(getApplicationContext(),2,intent,PendingIntent.FLAG_UPDATE_CURRENT);
右下∠时间的格式化 还有看看是否能查询到的log打印
activity_main.xml
&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout xmlns:android=&/apk/res/android&
xmlns:tools=&/tools&
xmlns:app=&/apk/res-auto&
android:id=&@+id/activity_main&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&vertical&
tools:context=&com.example.liuan.phonevideo.activity.MainActivity&&
&android.support.v7.widget.Toolbar
android:id=&@+id/toolbar&
android:layout_width=&match_parent&
android:layout_height=&?attr/actionBarSize&
&/android.support.v7.widget.Toolbar&
&FrameLayout
android:id=&@+id/fl_container&
android:layout_weight=&1&
android:layout_width=&match_parent&
android:layout_height=&0dp&/&
&com.roughike.bottombar.BottomBar
android:id=&@+id/bottomBar&
android:background=&@color/colorPrimary&
android:layout_width=&match_parent&
android:layout_height=&60dp&
app:bb_activeTabColor=&@android:color/white&
app:bb_inActiveTabColor=&#55ffffff&
app:bb_behavior=&shifting&
app:bb_tabXmlResource=&@xml/bottombar_tabs&/&
&/LinearLayout&
activity_music_player.xml
&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout xmlns:android=&/apk/res/android&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:background=&@drawable/music_bg&
android:orientation=&vertical&&
&RelativeLayout
android:id=&@+id/rl_top&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:padding=&5dp&&
&ImageView
android:id=&@+id/iv_back&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_centerVertical=&true&
android:layout_margin=&5dp&
android:src=&@drawable/selector_back&
android:id=&@+id/tv_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_centerHorizontal=&true&
android:layout_marginTop=&5dp&
android:text=&忘情水&
android:textColor=&@android:color/white&
android:textSize=&18sp& /&
android:id=&@+id/tv_artist&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_below=&@id/tv_title&
android:layout_centerHorizontal=&true&
android:text=&&
android:textColor=&#cccccc& /&
&/RelativeLayout&
&ImageView
android:id=&@+id/iv_wave&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_gravity=&center_horizontal&
android:src=&@drawable/animation_wave& /&
&com.example.liuan.phonevideo.lyic.LyncView
android:id=&@+id/lic_view&
android:layout_width=&match_parent&
android:layout_height=&0dp&
android:layout_weight=&1&
android:textColor=&@android:color/white&
android:textSize=&30dp& /&
android:id=&@+id/tv_time&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_gravity=&right&
android:layout_margin=&5dp&
android:text=&03:00/3:48&
android:textColor=&@android:color/white& /&
android:id=&@+id/sb_progress&
style=&@android:style/Widget.SeekBar&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:layout_margin=&5dp&
android:maxHeight=&3dp&
android:minHeight=&3dp&
android:progress=&50&
android:progressDrawable=&@drawable/audio_seekbardrawable&
android:thumb=&@mipmap/audio_seek_thumb& /&
&LinearLayout
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:gravity=&center_vertical&
android:orientation=&horizontal&
android:padding=&5dp&&
&ImageView
android:id=&@+id/iv_playmode&
android:layout_width=&0dp&
android:layout_height=&wrap_content&
android:layout_weight=&1&
android:src=&@drawable/selector_playmode_shuffle& /&
&ImageView
android:id=&@+id/iv_pre&
android:layout_width=&0dp&
android:layout_height=&wrap_content&
android:layout_weight=&1&
android:src=&@drawable/selector_pre& /&
&ImageView
android:id=&@+id/iv_play_pause&
android:layout_width=&0dp&
android:layout_height=&wrap_content&
android:layout_weight=&1&
android:src=&@drawable/selector_play& /&
&ImageView
android:id=&@+id/iv_next&
android:layout_width=&0dp&
android:layout_height=&wrap_content&
android:layout_weight=&1&
android:src=&@drawable/selector_next& /&
&ImageView
android:id=&@+id/iv_list&
android:layout_width=&0dp&
android:layout_height=&wrap_content&
android:layout_weight=&1&
android:src=&@drawable/selector_list& /&
&/LinearLayout&
&/LinearLayout&
fragment_vbang.xml
&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout xmlns:android=&/apk/res/android&
android:orientation=&vertical& android:layout_width=&match_parent&
android:layout_height=&match_parent&&
android:id=&@+id/lv_vbang&
android:divider=&@null&
android:dividerHeight=&0dp&
android:layout_width=&match_parent&
android:layout_height=&match_parent&&&/ListView&
&/LinearLayout&
item_music.xml
&?xml version=&1.0& encoding=&utf-8&?&
&android.support.v7.widget.CardView
xmlns:android=&/apk/res/android&
xmlns:app=&/apk/res-auto&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
app:cardUseCompatPadding=&true&
android:foreground=&?attr/selectableItemBackground&
app:cardElevation=&4dp&
&LinearLayout
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&horizontal&
android:padding=&5dp&&
&ImageView
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_margin=&5dp&
android:src=&@mipmap/music_default_bg& /&
&LinearLayout
android:layout_width=&0dp&
android:layout_height=&wrap_content&
android:layout_marginLeft=&5dp&
android:layout_marginTop=&5dp&
android:layout_weight=&1&
android:orientation=&vertical&&
android:id=&@+id/tv_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:text=&歌曲名字& /&
android:id=&@+id/tv_artist&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:text=&艺术家&
android:textColor=&#ffcccccc& /&
&/LinearLayout&
android:id=&@+id/tv_size&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_margin=&5dp&
android:text=&3.0MB&
android:textColor=&#ffcccccc&
android:textSize=&16sp& /&
&/LinearLayout&
&/android.support.v7.widget.CardView&
notification_big.xml
&?xml version=&1.0& encoding=&utf-8&?&
&RelativeLayout xmlns:android=&/apk/res/android&
android:id=&@+id/rl_notification&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:padding=&5dp&&
&ImageView
android:id=&@+id/iv_icon&
android:layout_width=&100dp&
android:layout_height=&100dp&
android:src=&@drawable/music_default_bg&
android:layout_margin=&5dp&/&
android:id=&@+id/tv_notification_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_marginTop=&5dp&
android:text=&忘情水&
android:textAppearance=&@android:style/TextAppearance.StatusBar.EventContent.Title&
android:layout_centerHorizontal=&true&
android:textSize=&20sp&/&
android:id=&@+id/tv_notification_artist&
android:layout_below=&@id/tv_notification_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:text=&刘德华&
android:layout_centerHorizontal=&true&
android:textAppearance=&@android:style/TextAppearance.StatusBar.EventContent&
android:textSize=&18sp&/&
&LinearLayout
android:layout_toRightOf=&@id/iv_icon&
android:layout_below=&@id/tv_notification_artist&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:orientation=&horizontal&&
&ImageView
android:id=&@+id/iv_notification_pre&
android:layout_width=&0dp&
android:layout_weight=&1&
android:layout_height=&40dp&
android:src=&@drawable/selector_pre&
android:layout_margin=&5dp&/&
&ImageView
android:id=&@+id/iv_notification_playPause&
android:layout_width=&0dp&
android:layout_weight=&1&
android:layout_height=&40dp&
android:src=&@drawable/selector_play&
android:layout_margin=&5dp&/&
&ImageView
android:id=&@+id/iv_notification_next&
android:layout_width=&0dp&
android:layout_weight=&1&
android:layout_height=&40dp&
android:src=&@drawable/selector_next&
android:layout_margin=&5dp&/&
&/LinearLayout&
&ImageView
android:id=&@+id/iv_notification_cancel&
android:layout_alignParentRight=&true&
android:layout_width=&30dp&
android:layout_height=&30dp&
android:src=&@drawable/audio_seek_thumb&/&
&/RelativeLayout&
notification_normal.xml
&?xml version=&1.0& encoding=&utf-8&?&
&RelativeLayout xmlns:android=&/apk/res/android&
android:id=&@+id/rl_notification&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:padding=&5dp&&
&ImageView
android:id=&@+id/iv_icon&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:src=&@drawable/music_default_bg&
android:layout_margin=&5dp&/&
android:id=&@+id/tv_notification_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_toRightOf=&@id/iv_icon&
android:layout_marginTop=&5dp&
android:text=&忘情水&
android:textColor=&#000000&
android:textSize=&18sp&/&
android:id=&@+id/tv_notification_artist&
android:layout_below=&@id/tv_notification_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_toRightOf=&@id/iv_icon&
android:text=&刘德华&
android:textColor=&#&
android:textSize=&16sp&/&
&ImageView
android:id=&@+id/iv_notification_next&
android:layout_alignParentRight=&true&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:src=&@drawable/selector_next&
android:layout_margin=&5dp&/&
&ImageView
android:id=&@+id/iv_notification_pre&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_toLeftOf=&@id/iv_notification_next&
android:src=&@drawable/selector_pre&
android:layout_margin=&5dp&/&
&/RelativeLayout&
放在新建文件夹layout-v21 用的是布局适配
notification_big.xml
&?xml version=&1.0& encoding=&utf-8&?&
&RelativeLayout xmlns:android=&/apk/res/android&
android:id=&@+id/rl_notification&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:padding=&5dp&&
&ImageView
android:id=&@+id/iv_icon&
android:layout_width=&100dp&
android:layout_height=&100dp&
android:src=&@drawable/music_default_bg&
android:layout_margin=&5dp&/&
android:id=&@+id/tv_notification_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_marginTop=&5dp&
android:text=&忘情水&
android:textAppearance=&@android:style/TextAppearance.Material.Notification.Title&
android:layout_centerHorizontal=&true&
android:textSize=&20sp&/&
android:id=&@+id/tv_notification_artist&
android:layout_below=&@id/tv_notification_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:text=&刘德华&
android:layout_centerHorizontal=&true&
android:textAppearance=&@android:style/TextAppearance.Material.Notification.Line2&
android:textSize=&18sp&/&
&LinearLayout
android:layout_toRightOf=&@id/iv_icon&
android:layout_below=&@id/tv_notification_artist&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:orientation=&horizontal&&
&ImageView
android:id=&@+id/iv_notification_pre&
android:layout_width=&0dp&
android:layout_weight=&1&
android:layout_height=&40dp&
android:src=&@drawable/selector_pre&
android:layout_margin=&5dp&/&
&ImageView
android:id=&@+id/iv_notification_playPause&
android:layout_width=&0dp&
android:layout_weight=&1&
android:layout_height=&40dp&
android:src=&@drawable/selector_play&
android:layout_margin=&5dp&/&
&ImageView
android:id=&@+id/iv_notification_next&
android:layout_width=&0dp&
android:layout_weight=&1&
android:layout_height=&40dp&
android:src=&@drawable/selector_next&
android:layout_margin=&5dp&/&
&/LinearLayout&
&ImageView
android:id=&@+id/iv_notification_cancel&
android:layout_alignParentRight=&true&
android:layout_width=&30dp&
android:layout_height=&30dp&
android:src=&@drawable/audio_seek_thumb&/&
&/RelativeLayout&
notification_normal.xml
&?xml version=&1.0& encoding=&utf-8&?&
&RelativeLayout xmlns:android=&/apk/res/android&
android:id=&@+id/rl_notification&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:padding=&5dp&&
&ImageView
android:id=&@+id/iv_icon&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:src=&@drawable/music_default_bg&
android:layout_margin=&5dp&/&
android:id=&@+id/tv_notification_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_toRightOf=&@id/iv_icon&
android:layout_marginTop=&5dp&
android:text=&忘情水&
android:textAppearance=&@android:style/TextAppearance.Material.Notification&
android:textSize=&18sp&/&
android:textAppearance=&@android:style/TextAppearance.Material.Notification.Line2&
android:id=&@+id/tv_notification_artist&
android:layout_below=&@id/tv_notification_title&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_toRightOf=&@id/iv_icon&
android:text=&刘德华&
android:textColor=&#&
android:textSize=&16sp&/&
&ImageView
android:id=&@+id/iv_notification_next&
android:layout_alignParentRight=&true&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:src=&@drawable/selector_next&
android:layout_margin=&5dp&/&
&ImageView
android:id=&@+id/iv_notification_pre&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_toLeftOf=&@id/iv_notification_next&
android:src=&@drawable/selector_pre&
android:layout_margin=&5dp&/&
&/RelativeLayout&
res/xml/bottombar_tabs.xml
帧动画布局(animationDra)iv.getDra获取对象 然后.start开启
animation_wave.xml
&?xml version=&1.0& encoding=&utf-8&?&
&animation-list xmlns:android=&/apk/res/android&&
&item android:drawable=&@drawable/audio_anim_01& android:duration=&200&/&
&item android:drawable=&@drawable/audio_anim_02& android:duration=&200&/&
&item android:drawable=&@drawable/audio_anim_03& android:duration=&200&/&
&item android:drawable=&@drawable/audio_anim_04& android:duration=&200&/&
&item android:drawable=&@drawable/audio_anim_05& android:duration=&200&/&
&item android:drawable=&@drawable/audio_anim_06& android:duration=&200&/&
&item android:drawable=&@drawable/audio_anim_07& android:duration=&200&/&
&item android:drawable=&@drawable/audio_anim_08& android:duration=&200&/&
&item android:drawable=&@drawable/audio_anim_09& android:duration=&200&/&
&/animation-list&
audio_seekbardrawable.xml
&?xml version=&1.0& encoding=&utf-8&?&&!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the &License&);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an &AS IS& BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
&layer-list xmlns:android=&/apk/res/android&&
&item android:id=&@android:id/background&&
&corners android:radius=&5dip& /&
&solid android:color=&#c0c1c7& /&
&item android:id=&@android:id/secondaryProgress&&
&scale android:scaleWidth=&100%&&
&selector&
&item android:state_enabled=&false&&
&color android:color=&@android:color/transparent& /&
&item android:drawable=&@drawable/abc_scrubber_primary_mtrl_alpha& /&
&/selector&
&item android:id=&@android:id/progress&&
&corners android:radius=&5dip& /&
&solid android:color=&@color/colorMusicProgress& /&
&/layer-list&
selector_back.xml
selector_list.xml
selector_next.xml
selector_pause.xml
selector_play.xml
selector_playmode_list.xml
selector_playmode_shuffle.xml
selector_playmode_single.xml
selector_pre.xml
图片放这个里面就可以了
drawable-xhdpi
values 目录下的几个文件
colors.xml
dimens.xml
strings.xml
styles.xml
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.roughike:bottom-bar:2.0.2'
compile 'com.android.support:cardview-v7:24.2.0'
&?xml version=&1.0& encoding=&utf-8&?&
&manifest xmlns:android=&/apk/res/android&
package=&com.example.liuan.phonevideo&&
&uses-permission android:name=&android.permission.READ_EXTERNAL_STORAGE& /&
&application
android:allowBackup=&true&
android:icon=&@mipmap/ic_launcher&
android:label=&@string/app_name&
android:supportsRtl=&true&
android:theme=&@style/AppTheme&&
&activity android:name=&.activity.MainActivity&&&/activity&
android:name=&.activity.SplashActivity&
android:theme=&@style/AppTheme.FullScreen&&
&intent-filter&
&action android:name=&android.intent.action.MAIN& /&
&category android:name=&android.intent.category.LAUNCHER& /&
&/intent-filter&
&/activity&
&activity android:name=&.activity.MusicPlayerActivity&&&/activity&
&service android:name=&.service.MusicPlayerService&/&
&/application&
&/manifest&
到了这个地方 你肯定要试一试..我衷心的祝福你能成功。但是有的模拟器可能没有这个数据库 。所以最好建议真机测试。
排名:千里之外
(47)(3)(1)(1)}

我要回帖

更多关于 自己制作音乐播放器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信