音乐播放器功能的实现,歌词lrc显示,播放过程中来电

 
 
5.1 音乐播放器功能的实现。(社区ID:clarck)
音乐播放器最主要的功能有:播放、暂停、上一首、下一首、歌曲拖拽播放、在线播放、后
台播放、播放歌曲信息状态栏提醒、搜索歌曲、歌词同步、扫描歌曲、换肤、设置铃声、歌曲信
息、下载歌曲、均衡器调节、来电时音乐播放器的音量调节等等。
音乐播放器的功能就是前台要实现什么功能通过接口语言告诉后台,具体怎么实现让
service去实现,以达到前台和服务各自实现自己的功能,又能相结合通信的目的。
其中,网络搜索要用到xml解析,换肤主要是改变background,以下是一些名词的解释:
Service:要实现后台播放就要结合到Android中的服务
AndroidInterfaceDefiniti onLanguage:跨进程通信机制AIDL(接口描述语言)
NotificationManager:通知管理器
Handle:消息机制
TelephonyManager:手机来电接收器管理
RingtoneManager:铃声管理器
WindowManager:屏幕亮度调节
service中通过Binder来实现和IPlayback绑定
5.1.1 AIDL的使用:
以aidl为文件结尾,定义一些供前台调用的接口,接口全部在service中实现。以达到和
service进行通信的目的,实现跨进程调用。
IPlayback.aidl
interface IPlayback {
//开始播放
void start();
//暂停播放
void pause();
//停止播放
void stop();
//释放资源
void release();
//上一首
void previous();
//下一首
void next() ;
//获取正在播放的音乐的ID
int getId() ;
//获取正在播放的音乐的标题
java.lang.String getTitle();
//获取正在播放的音乐的艺术家
java.lang.String getArtist() ;
//获取正在播放的音乐的专辑
java.lang.String getAlbum() ;
//获取当前播放的位置
int getDuration();
//获取当前播放的时间
int getTime();
//拖放
void seek(int time);
//判断是否正在播放
boolean isPlaying() ;
}
java.lang.String getArtist() ;
//获取正在播放的音乐的专辑
java.lang.String getAlbum() ;
//获取当前播放的位置
int getDuration();
//获取当前播放的时间
int getTime();
//拖放
void seek(int time);
//判断是否正在播放
boolean isPlaying() ;
}
public void start() throws RemoteException {
// TODO Auto-generated method stub
if(state == STOP)
{
//如果当前状态为STOP,调用prepare()重新播放歌曲
try {
player.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if (state == PAUSE) {
player.start();
state=PLAYING;
}
public void seek(int time) throws RemoteException {
// TODO Auto-generated method stub
player.seekTo(time);
}
public void release() throws RemoteException {
// TODO Auto-generated method stub
//释放MediaPlayer对象
player.release();
player=null;
state=IDLE;
}
public void previous() throws RemoteException {
// TODO Auto-generated method stub
//播放上一首歌曲
if(!cursor.moveToPrevious())
cursor.moveToLast();
_play();
}
public void pause() throws RemoteException {
// TODO Auto-generated method stub
//暂停播放
if (player.isPlaying()) {
player.pause();
state = PAUSE;
}
}
public void next() throws RemoteException {
// TODO Auto-generated method stub
//播放下一首歌曲
_next();
if(player.isPlaying())
{
player.pause();
state=PAUSE;
}
}
public boolean isPlaying() throws RemoteException {
// TODO Auto-generated method stub
return player.isPlaying();
}
public String getTitle() throws RemoteException {
// TODO Auto-generated method stub
//读取正在播放歌曲的标题
return
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
}
public int getTime() throws RemoteException {
// TODO Auto-generated method stub
//获得当前的媒体时间
return player.getCurrentPosition();
}
public int getId() throws RemoteException {
// TODO Auto-generated method stub
if(cursor.getPosition() == -1)
{
return -1;
}
//获得当前正在播放歌曲的ID
return
cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
}
public int getDuration() throws RemoteException {
// TODO Auto-generated method stub
//获得当前歌曲的时长
return player.getDuration();
}
public String getArtist() throws RemoteException {
// TODO Auto-generated method stub
//读取正在播放歌曲的歌手信息
return
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST))
;
}
public String getAlbum() throws RemoteException {
// TODO Auto-generated method stub
//读取正在播放歌曲的专辑
return
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return binder;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
ContentResolver contentResolver=getContentResolver();
cursor=contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTEENT_URI,
null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if(nMgr!=null)
nMgr.cancel(R.string.notification_titile);
if(player!=null)
player.release();
}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
if(position!=-1)
{
cursor.moveToPosition(position);
_play();
}
}
private void _play() {
// TODO Auto-generated method stub
String
path=cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DAT
A));
try {
if(player==null)
{
player=new MediaPlayer();
player.setOnCompletionListener(completionListener);
player.setOnPreparedListener(preParedListener);
player.setOnErrorListener(errorListener);
}
else
{
player.reset();
}
player.setDataSource(path);
player.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void _next()
{
if(!cursor.moveToNext())
cursor.moveToFirst();
_play();
}
private OnErrorListener errorListener=new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
_next();
return true;
}
};
privateOnCompletionListe nercompletionListener=newOnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
if(!cursor.moveToNext())
cursor.moveToFirst();
_play();
}
};
private OnPreparedListener preParedListener= new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
player.start();
state=PLAYING;
Intent intent=new Intent(TRACK_UPDATE);
sendBroadcast(intent);
showNotification();
}
};
private void showNotification() {
CharSequence title = cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
Notification notifi = new Notification(R.drawable.stat_sample, title,
System.currentTimeMillis());
//设置Intent,以便用户可以从通知列表中返回PlayingActivity
PendingIntent pIntent = PendingIntent.getActivity(this, 0, new
Intent(this, Main.class), 0);
String message =
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST))
;
notifi.setLatestEventInfo(this, title, message, pIntent);
if (nMgr == null)
nMgr= (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
//通知用户,歌曲已经开始播放
nMgr.notify(R.string.notification_titile, notifi);
}
}
绑定服务类:
private IPlayback service;
//获取连接
private ServiceConnection connection=new ServiceConnection() {
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
// TODO Auto-generated method stub
//绑定成功后,获得IPlayback接口
service=IPlayback.Stub.asInterface(arg1);
//更新播放屏
handler.sendMessage(handler.obtainMessage(UPDATE));
}
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
service=null;
}
};
if(service==null)
{
Intent intent=new Intent(this,MusicService.class);
intent.putExtra("position", position);
startService(intent);
intent.removeExtra("position");
//绑定到服务
if(false==bindService(intent, connection,
Context.BIND_AUTO_CREATE))
{
finish();
}
}
1、TelephonyManager:手机来电接收器管理
class IncomingSMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (intent.getAction().equals("android.intent.action.ANSWER")) {
//手机来电接收器管理
TelephonyManager telephonymanager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
int callMode = Integer.parseInt(sp.getString(
getString(R.string.callactionkey), "0"));
//当前音量大小
current = am.getStreamVolume(AudioManager.STREAM_MUSIC);
switch (telephonymanager.getCallState()) {
case TelephonyManager.CALL_STATE_RINGING:
//根据设置模式完成不同的动作
switch (callMode) {
case 1:
//暂停播放
smplayer.pause();
break;
case 2:
//调低音量
am.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0);
break;
default:
break;
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK: //挂机后的处理
//根据设置模式完成不同的动作
switch (callMode) {
case 1:
//重新开始播放
smplayer.resume();
break;
case 2:
//还原音量
am.setStreamVolume(AudioManager.STREAM_MUSIC, current,
0);
break;
default:
break;
}
break;
default:
break;
}
}
}
}
2、铃声管理器:RingtoneManager
//来电铃声:
RingtoneManager.setActualDefaultRingtone Uri(MainView.this,
RingtoneManager.TYPE_RINGTONE,Uri.parse("file:sdcard/ringtone/music.m
p3");
//通知铃声,
RingtoneManager.setActualDefaultRingtone Uri(MainView.this,
RingtoneManager.TYPE_NOTIFICATION,Uri.parse("file:sdcard/ringtone/mus
ic.mp3");
//闹钟铃声
RingtoneManager.setActualDefaultRingtone Uri(MainView.this,
RingtoneManager.TYPE_ALARM,Uri.parse("file:sdcard/ringtone/music.mp3")
;
//所有铃声
RingtoneManager.setActualDefaultRingtone Uri(MainView.this,
RingtoneManager.TYPE_ALL,Uri.parse("file:sdcard/ringtone/music.mp3");
3、屏幕亮度管理:WindowManager
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.screenBrightness = 1.0f; //1.0f表示亮度为最亮、0.1f表示最暗
getWindow().setAttributes(lp);
4、打开系统设置界面:
Intent intent=new Intent();
intent.setComponent(new ComponentName("com.android.settings",
"com.android.settings.Settings"));
startActivity(intent);
5、进入无线网络配置界面:
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
5.2 自动下载歌词与歌词的解析。(eoe社区ID:clarck)
研究了对于歌词的下载和歌词的解析,网上找了好久没有找到很好的方法,于是自己研究了一下,
贡献上自己的方法,希望以后有更好的方法。
5.2.1歌词下载代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class HttpDownloader {
private static URL url = null;
public String download(String urlStr) {
StringBuffer sb = new StringBuffer();
String line = null;
BufferedReader buffer = null;
try {
//创建一个URL对象
url = new URL(urlStr);
//创建一个Http连接
HttpURLConnectionurlConn =(HttpURLConnection)url.openConnection();
//使用IO流读取数据
buffer = new BufferedReader(new
InputStreamReader(urlConn.getInputStream()));
while ((line = buffer.readLine()) != null) {
sb.append(line+"\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
buffer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return sb.toString();
}
public static void main(String[] args) {
//这里通过拼参数进去,得到URL地址
String
Url=http://mp3.sogou.com/gecisearch.so?hl=zh-cn&query=”+MusicName+”&as=false&
st=&ac=1&pf=&class=5&gecisearch.so=";
HttpDownloader downloader=new HttpDownloader();
String ne=downloader.download(Url);
//通过正则表达式来匹配到歌词的具体下载地址
Pattern pattern = Pattern.compile("((downlrc.jsp?).*(LRC歌词下载))");
Matcher matcher= pattern.matcher(ne);
if(matcher.find())
{
String wangzhi=matcher.group(0);
String down=wangzhi.substring(0, wangzhi.indexOf('"'));
System.out.println(ne);
//拼接上host
String down_address = "http://mp3.sogou.com/"+down ;
System.out.println(downloader.download(down_address));
}
}
5.2.2 实例讲述该如何自动下载
1、歌曲名为:后来
直接讲MusicName改为:“后来”然后拼接进去。
以下是得到的结果:
[by:昨夜星辰昨夜风]
[00:03.21]刘若英:后来
[05:16.43][00:05.26]词:施人诚曲:玉城干春编曲:王继康
[04:03.05][03:37.50][02:33.36][00:12.18]后来,
[04:04.79][03:39.30][02:35.11][00:14.26]我总算学会了如何去爱。
[04:09.72][03:44.17][02:40.10][00:19.01]可惜你早已远去,
[04:12.56][03:46.92][02:42.88][00:21.87]消失在人海。
[04:15.82][03:50.10][02:46.12][00:25.14]后来,
[04:17.82][03:52.09][02:48.08][00:27.05]终于在眼泪中明白,
[04:22.53][03:56.77][02:52.83][00:31.93]有些人一旦错过就不再。
[00:39.67]槴子花,白花瓣,
[00:44.99]落在我蓝色百褶裙上。
[00:51.41]“爱你!”你轻声说。
[00:58.61]我低下头闻见一阵芬芳。
[01:04.92]那个永恒的夜晚,
[01:08.97]十七岁仲夏,
[01:11.88]你吻我的那个夜晚,
[01:17.98]让我往后的时光,
[01:21.31]每当有感叹,
[01:24.34]总想起当天的星光。
[01:30.84]那时候的爱情,
[01:36.46]为什么就能那样简单。
[01:42.48]而又是为什么人年少时,
[01:49.96]一定要让深爱的人受伤。
[01:56.06]在这相似的深夜里,
[02:00.32]你是否一样,
[02:03.32]也在静静追悔感伤。
[02:09.06]如果当时我们能不那么倔强,
[02:15.86]现在也不那么遗憾。
[03:25.13][02:20.91]你都如何回忆我,
[03:27.92][02:23.94]带著笑或是很沉默。
[03:31.14][02:27.19]这些年来有没有人能让你不寂寞。
[04:29.45]永远不会再重来,
[04:35.34]有一个男孩爱著那个女孩。
然后将该内容保存为.“后来.lrc”文件,以供解析。
2、解析歌词文件:
1)保存歌词的实体类:
1 public class Statement { private double time=0.0; //时间,单位为s,精确到0.01s private String lyric=""; //歌词 public double getTime() { return time; } public void setTime(double time) { this.time = time; }
*/
public void setTime(String time) {
String str[] = time.split(":|\\.");
this.time =
Integer.parseInt(str[0])*60+Integer.parseInt(str[1])+Integer.parseInt(str[2])
*0.01;
}
public String getLyric() {
return lyric;
}
public void setLyric(String lyric) {
this.lyric = lyric;
}
public void printLyric()
{
System.out.println(time+": "+lyric);
}
}
2)具体解析类:
BufferedReader bufferReader = null; //读取文件实例
public String title = ""; //歌曲题目
public String artist = ""; //演唱者
public String album = ""; //专辑
public String lrcMaker = ""; //歌词制作者
Vector<Statement> statements = new Vector<Statement>(); //歌词
public LrcData(String fileName) throws IOException{
FileInputStream file = new FileInputStream(fileName);
bufferReader=newBufferedReader(newInputStreamReader(file,"utf-8"));
//将文件数据读入内存
readData();
}
public void readData() throws IOException{
statements.clear();
String strLine;
//循环读入所有行
while(null != (strLine = bufferReader.readLine()))
{
//判断该行是否为空行
if("".equals(strLine.trim()))
{
continue;
}
//判断该行数据是否表示歌名
if(null == title || "".equals(title.trim()))
{
Pattern pattern = Pattern.compile("\\[ti:(.+?)\\]");
Matcher matcher = pattern.matcher(strLine);
if(matcher.find())
{
title=matcher.group(1);
continue;
}else
{
title="未知歌名";
continue;
}
}
//判断该行数据是否表示演唱者
if(null == artist || "".equals(artist.trim()))
{
Pattern pattern = Pattern.compile("\\[ar:(.+?)\\]");
Matcher matcher = pattern.matcher(strLine);
if(matcher.find())
{
artist=matcher.group(1);
continue;
}else
{
artist="未知演唱者";
continue;
}
}
//判断该行数据是否表示专辑
if(null == album || "".equals(album.trim()))
{
Pattern pattern = Pattern.compile("\\[al:(.+?)\\]");
Matcher matcher = pattern.matcher(strLine);
if(matcher.find())
{
album=matcher.group(1);
continue;
}else
{
album="未知专辑";
continue;
}
}
//判断该行数据是否表示歌词制作者
if(null == lrcMaker || "".equals(lrcMaker.trim()))
{
Pattern pattern = Pattern.compile("\\[by:(.+?)\\]");
Matcher matcher = pattern.matcher(strLine);
if(matcher.find())
{
lrcMaker=matcher.group(1);
continue;
}else
{
lrcMaker="未知歌词制作者";
continue;
}
}
//读取并分析歌词
int timeNum=0; //本行含时间个数
String str[] = strLine.split("\\]"); //以]分隔
for(int i=0; i<str.length; ++i)
{
String str2[] =str[i].split("\\["); //以[分隔
str[i] = str2[str2.length-1];
if(isTime(str[i])){
++timeNum;
}
}
for(int i=0; i<timeNum;++i) //处理歌词复用的情况
{
Statement sm = new Statement();
sm.setTime(str[i]);
if(timeNum<str.length) //如果有歌词
{
sm.setLyric(str[str.length-1]);
}
statements.add(sm);
}
if(1==str.length) //处理没有歌词的情况
{
Statement sm = new Statement();
sm.setTime(str[0]);
sm.setLyric("没有歌词");
statements.add(sm);
}
}
//将读取的歌词按时间排序
sortLyric();
}
public boolean isTime(String string)
{
String str[] = string.split(":|\\.");
if(3!=str.length)
{
return false;
}
try{
for(int i=0;i<str.length;++i)
{
Integer.parseInt(str[i]);
}
}
catch(NumberFormatException e)
{
return false;
}
return true;
}
public void sortLyric()
{
for(int i=0;i<statements.size()-1;++i)
{
int index=i;
double delta=Double.MAX_VALUE;
boolean moveFlag = false;
for(int j=i+1;j<statements.size();++j)
{
double sub;
if(0>=(sub=statements.get(i).getTime()-statements.get(j).getTime()))
{
continue;
}
moveFlag=true;
if(sub<delta)
{
delta=sub;
index=j+1;
}
}
if(moveFlag)
{
statements.add(index, statements.elementAt(i));
statements.remove(i);
--i;
}
}
}
public void printLrcDate()
{
System.out.println("歌曲名: "+title);
System.out.println("演唱者: "+artist);
System.out.println("专辑名: "+album);
System.out.println("歌词制作: "+lrcMaker);
for(int i=0;i<statements.size();++i)
{
statements.elementAt(i).printLyric();
}
}
public static void main(String[] args) throws IOException {
{
LrcData ld = new LrcData("F://歌词//后来.lrc"); //路径\\输入文件名
ld.printLrcDate();
}
}
3)解析得到的结果:
歌曲名:
演唱者:
专辑名:
歌词制作:昨夜星辰昨夜风
3210刘若英:后来
5260词:施人诚曲:玉城干春编曲:王继康
12180后来,
14260我总算学会了如何去爱。
19010可惜你早已远去,
21870消失在人海。
25140后来,
27050终于在眼泪中明白,
31930有些人一旦错过就不再。
39670槴子花,白花瓣,
44990落在我蓝色百褶裙上。
51410“爱你!”你轻声说。
58610我低下头闻见一阵芬芳。
64920那个永恒的夜晚,
68970十七岁仲夏,
71880你吻我的那个夜晚,
77980让我往后的时光,
81310每当有感叹,
84340总想起当天的星光。
90840那时候的爱情,
96460为什么就能那样简单。
102480而又是为什么人年少时,
109960一定要让深爱的人受伤。
116060在这相似的深夜里,
120320你是否一样,
123320也在静静追悔感伤。
129060如果当时我们能不那么倔强,
135860现在也不那么遗憾。
140910你都如何回忆我,
143940带著笑或是很沉默。
147190这些年来有没有人能让你不寂寞。
153360后来,
155110我总算学会了如何去爱。
160100可惜你早已远去,
162880消失在人海。
166120后来,
168080终于在眼泪中明白,
172830有些人一旦错过就不再。
205130你都如何回忆我,
207920带著笑或是很沉默。
211140这些年来有没有人能让你不寂寞。
217500后来,
219300我总算学会了如何去爱。
224170可惜你早已远去,
226920消失在人海。
230100后来,
232090终于在眼泪中明白,
236770有些人一旦错过就不再。
243050后来,
244790我总算学会了如何去爱。
249720可惜你早已远去,
252560消失在人海。
255820后来,
257820终于在眼泪中明白,
262530有些人一旦错过就不再。
269450永远不会再重来,
275340有一个男孩爱著那个女孩。
316430词:施人诚曲:玉城干春编曲:王继康
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值