学徒浅析Android——Role带来的角色扮演
在Q以前,如果我们的应用是一个短信或拨号之类的特殊应用,想要通知用户将我们的应用替换掉手机自带的预搭载应用,TelecomManager.ACTION_CHANGE_DEFAULT_DIALER和Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT就可以帮我们实现。但在Q上,google改变这种处理方案,并推出了一个新特性——Role/RoleManager。从文档介绍来看,是提供管理应用服务的,最常见的就是默认应用切换功能。
有了新的替代API,那么原先的TelecomManager.ACTION_CHANGE_DEFAULT_DIALER和Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT还能使用吗,很遗憾,虽然你可以写出来,也可以发出去,但是当你运行这两个action时,除了动作无响应外,你还会额外收到一条log:
Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT is removed for the calling package ,use RoleManager.createRequestRoleIntent() instead
即Q主动把你调用的action删除掉,再暗示你该用Role了。这个log是由于PermissionPolicyService#isActionRemovedForCallingPackage()主动规避TelecomManager.ACTION_CHANGE_DEFAULT_DIALER和Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT导致的,并且只在Q上生效。逻辑处理如下:
可以看出,这两个action已经被内部无效化了,Role是你唯一可选的路。Role将可设置的默认应用细分成8类,每一类对应一个特定的Role类型。Role的展示页面ReuqestRoleActivity针对调用发起者做了限制,只有同类型或者处于系统进程的应用才能调用Role服务。你用一个普通应用创建RoleManager,会发现它的isRoleAvailable()始终返回false的。
其实Role可以用一个通俗的例子来解释,假设我们的应用是生旦净末丑行当中的某个小角,戏台上要从所有的旦角中选一个当默认主角,戏台规定只有旦角行当的才可以参与选择。这个行当就是Role类型,戏台就是androidQ系统,参与的方式就是调用RoleManager请求。
通过上述的比喻,就可以理解google这么做的原因——减少服务的滥用,以往可以随意调用的action都会被淘汰掉。为此,针对Q我们的应用要通过配置权限或策略先成为一个特定的短信、浏览器、或者桌面应用后,才能通过RoleManager切换系统同类型的默认应用。截止到Q Beta4版后,Role相关角色和权限对应表如下:
可以看出,作为搭载的第一版,Role的类型并不是很成熟,还有类型存在未设置的状态,后续肯定会有调整。我目前用到的只有ROLE_SMS和ROLE_CALL_SCREENING,下面就以这两个角色为例,跟大家分享下Role的使用和注意事项。
使用方法:
- ROLE_SMS
Manifest.xml中必须在启动类中添加CATEGORY_DEFAULT和对应的角色API。
使用RoleManager获得Intent对象,继而请求Role处理,此时就可以弹出切换默认应用的弹窗了。具体代码如下:
- ROLE_CALL_SCREENING
Manifest.xml中需要在CallScreeningService的实现类中声明android.telecom.CallScreeningService。
<service android:name="你的应用中CallScreeningService的实现类" |
android:permission="android.permission.BIND_SCREENING_SERVICE"> |
<intent-filter> |
<action android:name="android.telecom.CallScreeningService"/> |
</intent-filter> |
</service> |
CallScreeningService的实现类主要重写onScreenCall(),这个方法是在受到来电时就会被触发的,你可以在这里对来电信息进行处理,将它封装到CallIdentification中,CallIdentification特意增加了对来电骚扰程度的判断,CallIdentification#setNuisanceConfidence()对应的级别共有5个,级别如下:
CONFIDENCE_NUISANCE 诈骗/骚扰电话
CONFIDENCE_LIKELY_NUISANCE 可能是诈骗/骚扰电话
CONFIDENCE_LIKELY_NOT_NUISANCE 可能不是诈骗/骚扰电话
CONFIDENCE_NOT_NUISANCE 非诈骗/骚扰电话
CONFIDENCE_UNKNOWN 未知来电
完整的一次来电信息处理代码如下:
public class CallScreeningServiceImplementation extends CallScreeningService {
@Override
public void onScreenCall(@NonNull Call.Details details) {
//来电时该方法会被触发,对来电信息进行设置
CallIdentification.Builder callIdentification = new CallIdentification.Builder();
//来电人名称
callIdentification.setName("Name");
//来电其他信息
callIdentification.setDescription("Description");
callIdentification.setDetails("Details");
//来电类型
callIdentification.setNuisanceConfidence(CONFIDENCE_LIKELY_NOT_NUISANCE);
// 将修改好的来电信息向默认的电话应用发送过去
provideCallIdentification(details,callIdentification.build());
}
}
对应的电话应用一侧,可以通过Call.Details.getCallIdentification()接受我们传过去的数据。
注意事项:
- 使用Role的前提是,你的应用必须是Role指定的角色应用,比如android.intent.category.HOME将你的应用指定为桌面应用,设置短信相关权限将你的应用指定为SMS应用。
- 对于createRequestRoleIntent()返回的Intent,不能给它添加诸如FLAG_ACTIVITY_NEW_TASK之类的flag,并且必须使用startActivityForResult(Intent, int)进行调用,其他诸如startActivity()是无效的。否则你会收到如下所示的警告日志:
package name cannot be null or empty: null
这个日志产生的原因就在Role的响应类RequestRoleActivity中。我们发起的Intent,最 终会交给PermissionController来处理。这是一个APK,它和Settings存在,Role处理页面是RequestRoleActivity。RequestRoleActivity#onCreate()中会获取两个参数,一个是mRoleName角色类型,就是我们在createRequestRoleIntent()中传入的类型。一个是mPackageName呼叫的应用包名。它的获取方式是getCallingPackage(),相关源码如下:
getCallingPackage()依赖于是否调用了startActivityForResult()、是否有明确的返回值这两个条件,只有这两个条件都满足的情况下,getCallingPackage()才能获取到当前发起请求的包名。另外如果你使用了FLAG_ACTIVITY_NEW_TASK,RequestRoleActivity会在一个新的任务栈中加载导致它没有返回值,同样会导致getCallingPackage()返回null。因此调用Role的方式只能是在不添加任何flag的情况下使用startActivityForResult来调用,即使你不需要后续onActivityForResult中的逻辑。
- 一旦你的应用通过Role成功设置为默认应用后,就无法再调用RoleManager进行切换了,这是因为在RequestRoleActivity#onCreate()中会判断调起的mPackageName是否已经是当前角色的持有者了。代码如下:
RoleManager roleManager = getSystemService(RoleManager.class);
List<String> currentPackageNames = roleManager.getRoleHolders(mRoleName);
if (currentPackageNames.contains(mPackageName)) {
Log.i(LOG_TAG, "Application is already a role holder, role: " + mRoleName
+ ", package: " + mPackageName);
reportRequestResult(PermissionControllerStatsLog
.ROLE_REQUEST_RESULT_REPORTED__RESULT__IGNORED_ALREADY_GRANTED);
setResult(RESULT_OK);
finish();
return;
}
学徒浅析Android——Role带来的角色扮演相关推荐
- 学徒浅析Android——Android7.0(N)对于自定义证书和非CA机构证书的适配校验
本篇文章已授权微信公众号 guolin_blog(郭霖)独家发布 对于Android N之前自定义或非CA证书的使用,一般有两种方式: 1.自定义X509TurstManager和Hostname ...
- 学徒浅析Android——Android原生下载机制针对0K大小文件下载异常的分析
本篇文章已授权微信公众号 guolin_blog(郭霖)独家发布 最近在进行一次测试用例中,发现测试手机在利用本地下载功能下载0K大小的文件时,进度条一直处于进度模糊状态中,虽然查看本地存储路径,发现 ...
- 学徒浅析Android开发:第三讲——Dialog的常用方法介绍(二)
经过(一)的基础介绍,现在小编将在(二)中给大家介绍以下几种效果: 1.点击查看组图(模拟QQ空间图片浏览) 2.缩略图放大(自定义Dialog) 3.动态加载进度条 一.点击产看组图(模拟QQ空间图 ...
- 《Android 游戏开发大全(第二版)》——6.4节角色扮演游戏
本节书摘来自异步社区<Android 游戏开发大全(第二版)>一书中的第6章,第6.4节角色扮演游戏,作者吴亚峰 , 于复兴 , 杜化美,更多章节内容可以访问云栖社区"异步社区& ...
- android 竖屏rpg游戏,可以竖屏玩的rpg角色扮演大型手游排行
游戏是目前绝大多数人放松的渠道,但是大部分人群是需要上班的,双休日休息还来不及玩什么游戏呢,但是我有办法解决这种问题,那就是找到竖屏游戏,可以单手操作的那种,就算在车上一手拉着扶手,另一只手也可以玩游 ...
- 时空之轮Android手柄,经典角色扮演类游戏 Android时空之轮
经典角色扮演类游戏 Android时空之轮 2013年03月12日 01:50作者:戴持编辑:戴持文章出处:泡泡网原创 分享 泡泡网手机频道3月12日 <时空之轮>(Chrono Trig ...
- 高性能游戏服务器架构设计,一种高性能大型多人在线角色扮演游戏服务器架构设计.doc...
一种高性能大型多人在线角色扮演游戏服务器架构设计 一种高性能大型多人在线角色扮演游戏服务器架构设计摘要:大型多人在线角色扮演游戏(Massively Multiplayer Online Role P ...
- For the king:出色的冒险,失败的角色扮演
<为了吾王>(简称FTK)是一款融合Roguelike.战棋.回合战斗与DND等多种元素的RPG 游戏,我们可以把它看为精简版"魔法门"与Roguelike的结合. 不 ...
- 探索女性角色扮演游戏Top Girl成功的秘诀
Top Girl 是一款女性题材的角色扮演游戏,只发布了短短两周,便超越了<愤怒的小鸟>等老牌劲旅,在 App Store 排行榜上登顶,成为玩家们追逐的热点. Top Girl 是什么? ...
最新文章
- Object-C---gt;Swift之(八)类和结构体
- Android GPS Location with Listener
- 田志刚:企业知识管理与用户创造内容(UGC)
- java 减法 位运算,位运算-实现加减乘除
- NLTK频率分类中定义的函数
- C#操作HttpClient工具类库
- 计算机格式化后数据恢复的基础,电脑硬盘格式化后还能恢复吗
- android app 移植到pc,微软开发新应用把Android app“移植”到Win Phone
- 【caffe-windows】 caffe-master 之图片转换成lmdb or leveldb
- Python关键字和标识符
- Matlab Robitic Toolbox学习笔记Day1
- 什么是面向对象对象,什么是面向过程,什么是面向对象思想。
- tomcat8.0安装及配置教程
- Bilibili拜年祭启发的小小探索
- MyBatis 报错The error may exist in…….xml
- 使用Github上传本地项目代码
- 教育网Linux下赶mule
- linux常用的引导管理器,Linux引导管理器GRUB、GRUB 2和LILO简介
- NYOJ 366 (全排列)
- 线性代数 --- 用内积重新定义矩阵的转置(个人学习笔记)
热门文章
- Linux-权限管理
- 新世界!打开Selenium和PhantomJs的大门!--爬虫福音
- Spring 中的 Bean
- Android Studio设置代理后显示:Cause: dl.google.com:443 failed to respond错误
- python invalid literal for int_Python方法int()报错:invalid literal for int() with base 10
- 台式电脑右下角声音图标有红色×解决办法
- 都25了年薪还在二十万!你这是什么水平?程序员:才二十万,你不废了吗...
- [Garmin]小米2成功运行v大GARMIN2.14,详细总结
- java中如何获取字符的ASCII码
- faiss python安装_faiss部署初体验