在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的使用和注意事项。

使用方法:

  1. ROLE_SMS

Manifest.xml中必须在启动类中添加CATEGORY_DEFAULT和对应的角色API。

使用RoleManager获得Intent对象,继而请求Role处理,此时就可以弹出切换默认应用的弹窗了。具体代码如下:

  1. 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()接受我们传过去的数据。

注意事项:

  1. 使用Role的前提是,你的应用必须是Role指定的角色应用,比如android.intent.category.HOME将你的应用指定为桌面应用,设置短信相关权限将你的应用指定为SMS应用。
  2. 对于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中的逻辑。

  1. 一旦你的应用通过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带来的角色扮演相关推荐

  1. 学徒浅析Android——Android7.0(N)对于自定义证书和非CA机构证书的适配校验

    本篇文章已授权微信公众号 guolin_blog(郭霖)独家发布   对于Android N之前自定义或非CA证书的使用,一般有两种方式: 1.自定义X509TurstManager和Hostname ...

  2. 学徒浅析Android——Android原生下载机制针对0K大小文件下载异常的分析

    本篇文章已授权微信公众号 guolin_blog(郭霖)独家发布 最近在进行一次测试用例中,发现测试手机在利用本地下载功能下载0K大小的文件时,进度条一直处于进度模糊状态中,虽然查看本地存储路径,发现 ...

  3. 学徒浅析Android开发:第三讲——Dialog的常用方法介绍(二)

    经过(一)的基础介绍,现在小编将在(二)中给大家介绍以下几种效果: 1.点击查看组图(模拟QQ空间图片浏览) 2.缩略图放大(自定义Dialog) 3.动态加载进度条 一.点击产看组图(模拟QQ空间图 ...

  4. 《Android 游戏开发大全(第二版)》——6.4节角色扮演游戏

    本节书摘来自异步社区<Android 游戏开发大全(第二版)>一书中的第6章,第6.4节角色扮演游戏,作者吴亚峰 , 于复兴 , 杜化美,更多章节内容可以访问云栖社区"异步社区& ...

  5. android 竖屏rpg游戏,可以竖屏玩的rpg角色扮演大型手游排行

    游戏是目前绝大多数人放松的渠道,但是大部分人群是需要上班的,双休日休息还来不及玩什么游戏呢,但是我有办法解决这种问题,那就是找到竖屏游戏,可以单手操作的那种,就算在车上一手拉着扶手,另一只手也可以玩游 ...

  6. 时空之轮Android手柄,经典角色扮演类游戏 Android时空之轮

    经典角色扮演类游戏 Android时空之轮 2013年03月12日 01:50作者:戴持编辑:戴持文章出处:泡泡网原创 分享 泡泡网手机频道3月12日 <时空之轮>(Chrono Trig ...

  7. 高性能游戏服务器架构设计,一种高性能大型多人在线角色扮演游戏服务器架构设计.doc...

    一种高性能大型多人在线角色扮演游戏服务器架构设计 一种高性能大型多人在线角色扮演游戏服务器架构设计摘要:大型多人在线角色扮演游戏(Massively Multiplayer Online Role P ...

  8. For the king:出色的冒险,失败的角色扮演

    <为了吾王>(简称FTK)是一款融合Roguelike.战棋.回合战斗与DND等多种元素的RPG 游戏,我们可以把它看为精简版"魔法门"与Roguelike的结合. 不 ...

  9. 探索女性角色扮演游戏Top Girl成功的秘诀

    Top Girl 是一款女性题材的角色扮演游戏,只发布了短短两周,便超越了<愤怒的小鸟>等老牌劲旅,在 App Store 排行榜上登顶,成为玩家们追逐的热点. Top Girl 是什么? ...

最新文章

  1. Object-C---gt;Swift之(八)类和结构体
  2. Android GPS Location with Listener
  3. 田志刚:企业知识管理与用户创造内容(UGC)
  4. java 减法 位运算,位运算-实现加减乘除
  5. NLTK频率分类中定义的函数
  6. C#操作HttpClient工具类库
  7. 计算机格式化后数据恢复的基础,电脑硬盘格式化后还能恢复吗
  8. android app 移植到pc,微软开发新应用把Android app“移植”到Win Phone
  9. 【caffe-windows】 caffe-master 之图片转换成lmdb or leveldb
  10. Python关键字和标识符
  11. Matlab Robitic Toolbox学习笔记Day1
  12. 什么是面向对象对象,什么是面向过程,什么是面向对象思想。
  13. tomcat8.0安装及配置教程
  14. Bilibili拜年祭启发的小小探索
  15. MyBatis 报错The error may exist in…….xml
  16. 使用Github上传本地项目代码
  17. 教育网Linux下赶mule
  18. linux常用的引导管理器,Linux引导管理器GRUB、GRUB 2和LILO简介
  19. NYOJ 366 (全排列)
  20. 线性代数 --- 用内积重新定义矩阵的转置(个人学习笔记)

热门文章

  1. Linux-权限管理
  2. 新世界!打开Selenium和PhantomJs的大门!--爬虫福音
  3. Spring 中的 Bean
  4. Android Studio设置代理后显示:Cause: dl.google.com:443 failed to respond错误
  5. python invalid literal for int_Python方法int()报错:invalid literal for int() with base 10
  6. 台式电脑右下角声音图标有红色×解决办法
  7. 都25了年薪还在二十万!你这是什么水平?程序员:才二十万,你不废了吗...
  8. [Garmin]小米2成功运行v大GARMIN2.14,详细总结
  9. java中如何获取字符的ASCII码
  10. faiss python安装_faiss部署初体验