程序猿如何从产品的角度去提升应用的体验之Android权限优化篇

前言:大家平时在开发的过程中是否会遇到这种情况:很多产品体验上的细节,特别是涉及到技术相关的细节,产品与设计可能并不会给出详细的解决方案,甚至可能并不太关注这方面的体验细节。例如,应用的缓存清理机制该怎么实现?权限申请的时机应该放在哪?用户没有给予应用必要的权限该怎么处理......这种时候,作为一个开发人员,特别是对自家产品的使用体验有追求的开发人员,其实完全可以充当一回产品,从产品的角度出发去思考,该怎样在技术实现的细节上,让自家的APP体验变得更好。千万不要小瞧这些细节,一个产品的极致体验,就是由无数的细节堆砌而成的。

1. 应用通知权限的优化

众所周知,推送对于一个APP来说是很重要的功能。推送在好的产品设计中可以有效地提高产品活跃度,增加用户的忠诚度以及留存率。但是,用户有可能会在无意中把应用的通知权限给禁止了,导致收不到推送(用户主动禁止应用的通知权限除外)。例如,华为手机会在通知中心直接提示用户是否关掉某个应用的通知权限。如果用户,特别是小白用户一不小心把通知权限给禁止了,导致应用收不到推送,反而可能还会把这种情况当做bug来向客服反馈(任何时候都千万不要高估用户对于智能手机使用的了解,尤其是你的APP的目标用户还包括中老年人的时候)。

华为手机的推送中心

如果大家有细心观察的话会发现,当应用的通知权限被禁止的时候,体验好的应用会在适当的时机以及场景下出现提示,告知用户通知在应用中起到的作用,尝试去消除用户的不信任和谨慎心理,并引导用户去打开通知权限。

那么,我们怎么知道自己的应用程序通知权限被禁止了呢?如果被禁止了又该怎么办呢?下面就来说一下解决方案。

1.1 检测应用的通知权限状态

检测应用的通知权限其实比较简单。通过查询 官方文档 可以发现,在support库的API 24.0.0 版本,已经有现成的方法可以直接查询应用的通知权限状态:


  1. NotificationManagerCompat.from(this).areNotificationEnable(); 

但是,这就意味着应用的 compileSdkVersion 也需要与support库的版本保持一致。如果应用目前所使用的compileSdkVersion 低于 24.0.0 或者由于某些历史原因而不能将compileSdkVersion 升到 24.0.0以上,那么就没有办法检测到应用的通知权限了吗?

其实,办法还是有的。通过查看系统源码,可以发现,NotificationManagerCompat.from(this).areNotificationEnable() 这个方法在不同版本的SDK上会有不同的实现。


  1. /** 
  2.  
  3. * Returns whether notifications from the calling package are not blocked. 
  4.  
  5. */ 
  6.  
  7. public boolean areNotificationsEnabled() {  
  8.     return IMPL.areNotificationsEnabled(mContext, mNotificationManager); 
  9.  
  10. }  

IMPL是一个实现了Impl接口的实现类对象,而且在静态代码块中通过判断手机系统所使用的版本号来初始化不同的实现类:


  1. static {    if (BuildCompat.isAtLeastN()) { 
  2.         IMPL = new ImplApi24(); 
  3.     } else if (Build.VERSION.SDK_INT >= 19) { 
  4.         IMPL = new ImplKitKat(); 
  5.     }  else if (Build.VERSION.SDK_INT >= 14) { 
  6.         IMPL = new ImplIceCreamSandwich(); 
  7.     } else { 
  8.         IMPL = new ImplBase(); 
  9.     } 
  10.     SIDE_CHANNEL_BIND_FLAGS = IMPL.getSideChannelBindFlags(); 
  11. }  

当手机系统Android版本小于4.4.0的时候, areNotificationEnable()方法会默认返回true。所以,此方法只有在4.4.0以上的手机系统上才能返回准确的结果。


  1. /** 
  2.  * Returns whether notifications from the calling package are blocked. 
  3.  */ 
  4. public boolean areNotificationsEnabled() { 
  5.     INotificationManager service = getService(); 
  6.     try {        return service.areNotificationsEnabled(mContext.getPackageName()); 
  7.     } catch (RemoteException e) { 
  8.         throw e.rethrowFromSystemServer(); 
  9.     } 
  10. }  

这种反射的方式实际上就是通过AppOpsManager和AppOpsService去获取位于/data/system/目录下的文件Appops.xml里的数据。所以,这个系统源码里的方法可以单独抽取出来作为一个通用的检测通知权限状态的方法。有关AppOpsManager,这里先不做展开,等下在1.4章节单独说一下。

1.2 引导用户跳转到通知权限设置界面

既然已经能检测到应用的通知权限状态,当应用的通知权限被禁止的时候,应该出现提示告知用户通知在应用中起到的作用,并引导用户去打开通知权限。以下为跳转到通知权限设置的通用方法:


  1. public void toNotificationSetting() {    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
  2.         Intent intent = new Intent(); 
  3.         intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS"); 
  4.         intent.putExtra("app_package", this.getPackageName()); 
  5.         intent.putExtra("app_uid", this.getApplicationInfo().uid); 
  6.         startActivity(intent); 
  7.     } else if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) { 
  8.         Intent intent = new Intent(); 
  9.         intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 
  10.         intent.addCategory(Intent.CATEGORY_DEFAULT); 
  11.         intent.setData(Uri.parse("package:" + this.getPackageName())); 
  12.         startActivity(intent); 
  13.     } 
  14. }  

在5.0以上,可以直接跳转到某个应用的通知权限快捷设置界面。但是在5.0以下,暂时还没有找到可以直接跳转到通知权限设置界面的方法,所以目前的做法是跳转某个应用的设置界面,在设置界面列表中应该会有通知权限管理的入口。如果你有更好的做法,欢迎在评论中指出来。这里再另外抛出一个问题,供大家思考:关于通知权限提示的方案,应该在什么时机或场景下出现好?出现提示的频率为多少好呢?是只提示一次呢,还是只要用户没打开通知权限就一直提示呢?欢迎大家在留言中说出自己的看法。

1.3 当通知权限被关闭后,Toast可能无法正常工作的问题

虽然跟通知权限的优化没什么关系,不过在这里还是要提一下。这个是在调研通知权限优化问题的时候偶然发现的坑:在大部分的机型上,当应用的通知权限被关闭后,系统的 Toast会直接无法正常工作。

以下是我测试过的数据:

可以看出,这个坑影响的机型范围还是挺大的。为什么会这样呢?

查阅源码后可以发现 Toast 里也用到了NotificationManagerService。在Toast执行show()方法后,执行到enqueueToast()的时候如下:


  1. if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) {    if (!isSystemToast) { 
  2.         Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request.");        return; 
  3.     } 
  4. }  

原来这里也用到了检测通知权限的方法noteNotificationOp()。如果通知权限被禁止了,那么Toast也就无法正常工作。

对于Android手机来说,Toast在应用中随处可见,如果因为通知权限导致Toast不工作那么影响还是挺大的。所以,在这里建议大家寻找一下Toast的替代方案,不要在项目中直接使用系统自带的Toast。同样的,如果大家有什么好的解决方案,也欢迎在留言中指出来。

1.4 AppOpsManager的工作原理

既然上面提到了AppOpsManager,那么这里来简单地介绍一下它的工作原理。AppOpsManager的工作框架图如下:

Setting UI通过AppOpsManager与AppOpsService 交互,给用户提供入口管理各个app的操作。

AppOpsService具体处理用户的各项设置,用户的设置项存储在 /data/system/appops.xml文件中。

AppOpsService也会被注入到各个相关的系统服务中,进行权限操作的检验。

各个权限操作对应的系统服务(比如定位相关的Location Service,Audio相关的Audio Service等)中注入AppOpsService的判断。如果用户做了相应的设置,那么这些系统服务就要做出相应的处理。比如,LocationManagerSerivce的定位相关接口在实现时,会有判断调用该接口的app是否被用户设置成禁止该操作,如果有该设置,就不会继续进行定位。

2. 应用权限的提示优化

由于篇幅的原因,这里就拿相机权限来举例。假设需求如下:

在需要使用相机的场景下,先提前检测相机权限是否打开,如果没有打开,则尝试申请相机权限,如果用户还是拒绝,则出现权限提示,引导用户去开启相机权限。下面是微信的处理方式:

(1)6.0系统以上,先尝试申请相机权限,用户点击禁止后弹出引导界面

(2)6.0系统以下,用户点击保持禁止后弹出引导界面

在6.0以上,我们一般可以通过系统自带的方法来检测某个权限是否被允许:


  1. ActivityCompat.checkSelfPermission(context, permission) 

但是,在6.0以下,如果想检测相机权限,却没有一个很好的方法。最后,经过查阅各种资料,发现好像只能通过一种简单粗暴的方式去检测相机权限:


  1. /** 
  2.  * 在6.0系统以下,通过尝试打开相机的方式判断有无拍照权限 
  3.  * 
  4.  * @return 
  5.  */ 
  6. private boolean checkCameraPermissionUnderM() { 
  7.     boolean isCanUse = true; 
  8.     Camera mCamera = null; 
  9.     try { 
  10.         mCamera = Camera.open(); 
  11.         Camera.Parameters mParameters = mCamera.getParameters(); 
  12.         mCamera.setParameters(mParameters); 
  13.     } catch (Exception e) { 
  14.         isCanUse = false; 
  15.     }    if (mCamera != null) { 
  16.         try { 
  17.             mCamera.release(); 
  18.         } catch (Exception e) { 
  19.             e.printStackTrace();            return isCanUse; 
  20.         } 
  21.     }    return isCanUse; 
  22. }  

当使用这个方法的时候,在6.0以下的手机,一般调用 Camera.open()方法,如果相机权限没打开,会先弹出相机权限申请弹框。如果点击允许,那么该方法就会返回true,点击禁止则返回false。这里需要指出的是,如果你使用相机的方式是通过Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE)来跳转到系统的相机界面的话,那么即使应用的相机权限被禁止了,也还是可以正常使用相机来拍照的。这种情况下要不要做权限检查,就看个人的看法了。

不知道大家有没注意到,微信在6.0以上和6.0以下弹出的提示对话框有点不同。在6.0以上提供“去设置”的选项,点击会跳转到设置里的应用列表界面,在6.0以下仅仅是提示。这也是一个产品的细节。个人看法,因为在6.0以下,有些国产系统的权限管理根本就不在设置里面,而是需要到官方提供的手机管家类型应用里面才可以进行权限的管理。那么多的国产系统,需要适配有点困难,如果没有很好的解决方案,那么还不如不要擅自帮用户做决定。可以看得出微信在跳转到权限设置界面的适配上也经过了一番考量,最后选择了这种折中的方案。

说到这里,既然权限提示优化的思路已经有了,大家也可以在自己的项目中封装一个权限管理类,“检查权限-被禁止-尝试申请权限-被拒绝-弹出提示框-引导用户去打开权限”通过一个方法一气呵成。

3. 总结

本文涉及到的知识点可能并不深奥,更多的是想向大家展示一下,假如开发人员从产品的角度去提升应用的体验,可以从什么角度去切入。如果能给大家带来一些启发就好了。看完文章后,不凡思考一下,自己的应用在权限提示上的体验是否做到最好了呢?如果还有可以改善的地方,那么赶紧根据自家应用的实际情况,改善一下权限提示的体验吧。相信我,做了这件事,你的用户会感激你的。

本文作者:佚名

来源:51CTO

时间: 2025-01-21 05:40:32

程序猿如何从产品的角度去提升应用的体验之Android权限优化篇的相关文章

产品经理赶快去提升你的情商

摘要: 不久前,美国公布了一份权威调查,显示了美国近20年来政界和商界成功人士的平均智商仅在中等,而情商却很高.社会心理学家认为,一个人是否能取得成功,智商只有20%的决定作用 不久前,美国公布了一份权威调查,显示了美国近20年来政界和商界成功人士的平均智商仅在中等,而情商却很高.社会心理学家认为,一个人是否能取得成功,智商只有20%的决定作用,其余的80%来自其他因素,最关键的是情感智慧,亦称情商.情商由十五个要素构成,即: 乐群性,指的是善于.乐于同人打交道;稳定性,指的是不喜怒无常; 恃强

程序猿媳妇儿注意事项

作者: Arale  来源: 简书  发布时间: 2016-08-11 15:42  阅读: 121974 次  推荐: 705   原文链接   [收藏]   十一年前我和程序猿第一次见面,还是大一军训期间.我甚至不确定程序猿是否记得那是第一次见面.当时不小心装伪文艺参加了吉他社,想借一本吉他入门书,然后同在吉他社热心的海哥说他一同学有,就带着我去拿书了.于是我们第一次"见面"了,我只看见一个对着电脑,佝偻着背的背影......严重怀疑程序猿根本没抬头看一眼那个已经晒得像反转熊猫一样

程序猿离装逼有多远?

1. 着装 一个牛X的程序猿其实是根本没有时间去打理自己外貌的,所以,发型就要像爱因斯坦那样,头顶一脑袋鸡窝,充满了凌乱蓬松美,而且要让人觉得随时能从头发里掏出一个鸡蛋的感觉.还有必须胡子一大把,这样彰显了自信和从容,如果是不近视则以,一旦近视,就要戴上酒瓶底子那么厚的大眼镜,给人感觉一种科研工作者的风格.而牛X程序猿对自己着装也是有高要求的,不管是春夏秋冬,还是白天晚上,刮风下雨,一个牛X的程序猿都必须十分在意自己着装,T恤+大花裤衩子+拖鞋那是标配,一年365天都是风雨无阻.而换衣服则要保持

对产品经理的各种吐槽,程序猿看过来

产品经理有三宝:http://www.aliyun.com/zixun/aggregation/2279.html">山寨,改版,再推倒 产品经理说"你明白吧,这里向右划可以出菜单,然后需要一个闪烁的动画,还有,我想这个tab可以拉下来,你懂吧?".设计师说"别废话,把你要抄的产品给我看下." 某程序猿正在写代码,一美工同事着急跑过来说:不好了,产品经理被绑架了,劫匪要 10 万赎人,不然就用汽油烧死他,现在正在募捐呢,要不咱们也捐点.程序猿:好,大

程序猿日记S01E05-Do one thing and do it well

"Do one thing and do it well." 绝对优势 随着互联网技术的发展,程序猿的岗位也越来越细分.比如企业在招聘的时候,会区分前端开发岗.后端开发岗.不同岗位的程序猿,在各自领域的专精程度都是有一定优势的,但是也不排除那种很牛逼的程序猿,前后端都很牛逼,就是大家经常提到的全栈程序猿(coding方面的全栈).举个例子,Sophia和Antonio都会写前后端代码,Sophia每天(8小时)能最多能写32个前端组件或者16个后端组件:Antonio每天最多能写24个

《C语言点滴》一1.2 程序猿和互联网

1.2 程序猿和互联网 C语言点滴 虽然你可以对电脑的硬件要求不高,但是对另外一个功能还是应该严重关切一下的,那就是联网功能.最方便的联网方式无疑就是3G联网方式了,可以做到随时随地上网.我在北京上班的时候,地铁车厢里有时会有人拿着笔记本通过3G在上网.因为我还没有忙到这种程度,所以一般我在地铁上经常干的就是防范小偷.应付要饭的.还有偷眼看看周围的美女. 有了互联网,就有了一个巨大的宝藏,你需要了解一些知识,同时还需要能够利用一些工具从这个巨大的宝藏中获得你需要的信息和资源.本节的"搜索引擎&q

iOS APP体验设计:从程序猿和设计湿说起

iOS APP体验设计不像互联网的体验设计那样,有一堆的方法论和可以"借鉴"的案例. 目前除了苹果的<Human Interface Guidelines>和前Palm的<Zen of Palm>外,没有找到更好的设计哲学和方法论. 事实上,即便认真地研读了HIG和Zen of Palm,甚至是Oolon Colluphid的哲学巨作你也无法严格按照Guideline设计出一款出色的APP.其原因,得从程序猿和设计湿说起. 程序猿 vs 设计湿 最被思想处于上世

程序猿与设计狮之间的那些事儿

  很久没聊过设计师职场了,今天说回那个千古难题:工程师与设计师的1像素之争.设计师认为一像素至关重要,非改不可,工程师认为小题大做,精力没花在刀刃上,有的设计师也容易因此沮丧,如果你是其中之一,推荐来看会代码的设计师如何解决这件事. @JingDesign :无意挑起所谓的职位之间的矛盾,直到今天看到这样一篇文章的时候,是的,这是一篇关于程序猿和设计狮之间的文章,起源是这样的,一位网友在某社区上提了一个问题: 开发人员拒绝按照 UI 标注还原设计,如何让他理解精确还原的重要性,从而去修改代码?

程序猿转型AI必须知道的几件事!

更多深度文章,请关注云计算频道:https://yq.aliyun.com/cloud 历史上AI火过两次,但是最终都已销声匿迹作为结束.这次AI大火的原因:AlphaGo 4比1战胜李世石,相对于一些外行人的恐慌和恐惧,其实很多业内人员在这场世纪之战结束后,都为人类点上了一个大大的赞.因为对于了解AlphaGo背后技术的那些人来说,人类有如此的计算能力和宏观把握能力已经很了不起了.但是,就在前不久AlphaGo2.0在乌镇完胜了柯洁.事实还是证明了人类在某些方面还是有一定的缺陷,毕竟万事万物都