Android设置来电铃声、通知铃声、闹钟铃声中的坑
最新做项⽬,遇到⼀个铃声设置的
bug
,⼀直被延期了⼤半年,终于忍不住了,花了⼤半天时间来研究问题所在。其实这个功能百度⼀下有很
多,但⼤部分都是同⼀篇⽂章,我们项⽬⾥最开始就是参考的百度的代码⽚段来实现的,但是有个
bug
,对同⼀个
mp3
⽂件设置
来电铃声
后,然
后再设置成
通知铃声
或者
闹钟铃声
,那原来设置的来电铃声就会变成
未知铃声
,同时失效了。就是分析这个问题花了⼤半天时间,⽽我发现百度⾕
歌的这些⽂章都没提到这个点,经过反复的猜测调试,终于找到问题所在,最后发现其实也很简单,但也是个很容易被忽略的点(在后⾯
问题分
析
处提到),特此记录⼀下。
需求描述
如图,下载的mp3铃声,点击三个按钮分别实现设置三个铃声。设置成功后可以到系统设置铃⾳处查看
需求描述.png
编码实现
懒得看分析的看官可直接复制以下代码到⾃⼰⼯程,亲测ok)
注意看代码中注释的两个步骤,这是两个关键的地⽅。就是这个地⽅让我研究了⼤半天,有追求的看官的可以看继续往后
看原理分析和问题分析。
/**
*
*设置铃声
*
*@_RINGTONE来电铃声
*_NOTIFICATION通知铃声
*_ALARM闹钟铃声
*
*@parampath下载下来的mp3全路径
*@paramtitle铃声的名字
*/
publicstaticvoidtRing(Contextcontext,inttype,Stringpath,Stringtitle){
UrioldRingtoneUri=ualDefaultRingtoneUri(context,_RINGTONE);//系统当前通知铃声
UrioldNotification=ualDefaultRingtoneUri(context,_NOTIFICATION);//系统当前通知铃声
UrioldAlarm=ualDefaultRingtoneUri(context,_ALARM);//系统当前闹钟铃声
Filesdfile=newFile(path);
ContentValuesvalues=newContentValues();
(,olutePath());
(,title);
(_TYPE,"audio/mp3");
(_RINGTONE,true);
(_NOTIFICATION,true);
(_ALARM,true);
(_MUSIC,true);
Uriuri=tentUriForPath(olutePath());
UrinewUri=null;
UrinewUri=null;
StringdeleteId="";
try{
Cursorcursor=tentResolver().query(uri,null,+"=?",newString[]{path},null);
if(First()){
deleteId=ing(umnIndex("_id"));
}
LogTool.e("AGameRing","deleteId:"+deleteId);
tentResolver().delete(uri,
+"=""+olutePath()+""",null);
newUri=tentResolver().inrt(uri,values);
}catch(Exceptione){
tackTrace();
}
if(newUri!=null){
StringringStoneId="";
StringnotificationId="";
StringalarmId="";
if(null!=oldRingtoneUri){
ringStoneId=tPathSegment();
}
if(null!=oldNotification){
notificationId=tPathSegment();
}
if(null!=oldAlarm){
alarmId=tPathSegment();
}
UritRingStoneUri;
UritNotificationUri;
UritAlarmUri;
if(type==_RINGTONE||(deleteId)){
tRingStoneUri=newUri;
}el{
tRingStoneUri=oldRingtoneUri;
}
if(type==_NOTIFICATION||(deleteId)){
tNotificationUri=newUri;
}el{
tNotificationUri=oldNotification;
}
if(type==_ALARM||(deleteId)){
tAlarmUri=newUri;
}el{
tAlarmUri=oldAlarm;
}
ualDefaultRingtoneUri(context,_RINGTONE,tRingStoneUri);
ualDefaultRingtoneUri(context,_NOTIFICATION,tNotificationUri);
ualDefaultRingtoneUri(context,_ALARM,tAlarmUri);
switch(type){
_RINGTONE:
xt(licationContext(),"设置来电铃声成功!",_SHORT).show();
break;
_NOTIFICATION:
xt(licationContext(),"设置通知铃声成功!",_SHORT).show();
break;
_ALARM:
xt(licationContext(),"设置闹钟铃声成功!",_SHORT).show();
break;
}
}
}
原理分析
要将⼀个sd卡的mp3⽂件设置成为铃声,需要有两个操作
1、将mp3⽂件路径存到ContentProvider⾥,得到相应的uri
2、调⽤ualDefaultRingtoneUri(),传⼊相应的uri和需要设置的铃声类型即可。
注:ContentProvider可以简单的理解成⼀个系统数据库,返回的uri其实就是这个数据库⾥某⼀条数据的唯⼀标识,含有_id。
⽤getActivity().getContentResolver().query这个⽅法可以查询到相关数据。
...
(_RINGTONE,true);
(_NOTIFICATION,true);
(_ALARM,true);
(_MUSIC,true);
...
这⼀堆其实就是表⾥的字段名和值,有⽤没有就看你怎么运⽤
问题分析
问题主要出在第⼀步。
要将mp3路径存到ContentProvider⾥,需要调⽤getActivity().getContentResolver().inrt()⽅法,但是⾥⾯原来有这个
铃声了的话,是插⼊不成功的。这个时候为了保险起见需要调⽤⼀次删除⽅法
getActivity().getContentResolver().delete(),这两部也基本上成了标配,⽹上的⽂章⼤部分也就这两步就得到了需要
的uri。
如果没有像我这⾥提到的需求,对同⼀个mp3可以分开分别设置的话就没有我这个bug。
问题就出在delete这个步骤,假设对⼀个铃声先设置了来电铃声得到
_id=1000
的
uri
,然后再讲这个mp3设置为通知铃⾳,那么在设置通知铃声
的时候掉的delete⽅法会将
_id=1000
的这个数据删了,因为这次要插⼊的记录和上⼀次⼀样的,然后再插⼊新的得到
_id=1001
的uri,这个时候通
知铃声就是
_id=1001
的uri,⽽之前设置的来电铃声读取的
_id=1000
的记录就没有了,查看铃声的时候就是未知铃⾳了。
找到问题所在后,我们就解决这个问题。
所以我在delete之前先进⾏了⼀次query操作,如果查到了就把那条记录的_id记录下来,后⾯再设置铃声的时候将三个类型的铃声的当前设置的
uri通过
tPathSegment()
得到其_id,然后和刚刚删除的
_id(deleteId)
进⾏对⽐,如果发现⼀样就说明之前这个类型的铃声就是我现在要插⼊
的铃声,就再把新的
_id=1001
的uri设置进去,否则就把得到的系统的uri再设置⼀次,或者不做操作。
最后
当然这只是其中⼀种⽅法,还有其他⽅法这⾥就不再赘述了。
本文发布于:2023-03-10 10:31:37,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/1678415498203197.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:怎么设置闹钟铃声.doc
本文 PDF 下载地址:怎么设置闹钟铃声.pdf
留言与评论(共有 0 条评论) |