如何在Activity中获取调用者 – getReferrer()

前言

为什么要在Activity中获取调用者?
主要是安全定制两个方面的需求吧。

  • 安全需求:
    一般Activity如果已经对外开放了(即exported为true,或者加了Intent-filter),那么对Activity的保护就会降低,形成Activity攻击面,引入了风险。如果只对某几个app开放其Activity,则可以获取调用者的信息,并进行控制。

  • 定制需求:
    如果被启动的Activity想对特定的调用者进行定制操作,则需要知道调用者是谁。


在Activity中获取调用者的方法

注:先列出所有可能的方法,后面会给出哪些方法可行。

  • Binder.getCallingUid()Binder.getCallingPid(),然后根据uid,pid查找到包名

  • Activity的 getCallingPackage()getCallingActivity()

  • Activity的 getReferrer()【注意:Android 5.1(Api level 22)中才引入的】

  • 反射的方式获取Activity的 mReferrer: reflectGetReferrer()【注:自定义函数,目的是获取到 android.app.Activity类的 mReferrer的值,也需要Api level 22(含)之后才能使用】

这里先给出结论:

  • 方法1:不能在调用者startActivity()的时候获取到调用者的包名,只能用于Activity用到的Binder同步调用的地方。

  • 方法2: 在特定情况下可以使用getCallingPackage()getCallingActivity(),即如果Activity是通过startActivityForResult启动的,则可以使用。

  • 方法3: Activity的getReferrer()是不可靠的,因为调用者可以自己设置referrer的值。

  • 方法4:是对方法3的改进,消除getReferrer()可能返回的不可靠的值,直接获取可靠的mReferrer值(目前来看是可靠的)。


关于mReferrer的细节

Activity的getReferrer()

需要注意的是,此方法是在Android 5.1 (Api level 22)中引入的,Android 5.1之前是不能使用的。

Intent.java

public static final String EXTRA_REFERRER= "android.intent.extra.REFERRER";public static final String EXTRA_REFERRER_NAME= "android.intent.extra.REFERRER_NAME";

Activity.java

public Uri getReferrer() {Intent intent = getIntent();// 优先从Intent的Intent.EXTRA_REFERRER数据获取Uri,作为referrerUri referrer = intent.getParcelableExtra(Intent.EXTRA_REFERRER);if (referrer != null) {return referrer;}// 如果之前没有获取到,则从intent的Intent.EXTRA_REFERRER_NAME数据获取,并转换成UriString referrerName = intent.getStringExtra(Intent.EXTRA_REFERRER_NAME);if (referrerName != null) {return Uri.parse(referrerName);}// 如果上面都没有获取到,则将mReferrer转换成android-app://的形式if (mReferrer != null) {return new Uri.Builder().scheme("android-app").authority(mReferrer).build();}return null;// 都没获取到的话,返回null}

反射的方式获取Activity的mReferrer

需要注意的是,此方法是基于getReferrer()(mReferrer)的,所以也必须在Android 5.1 (Api level 22)及 5.1 之后才能用。

自定义方法:

private String reflectGetReferrer() {try {Class activityClass = Class.forName("android.app.Activity");Field refererField = activityClass.getDeclaredField("mReferrer");refererField.setAccessible(true);String referrer = (String) refererField.get(MainActivity.this);return referrer;} catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException e) {e.printStackTrace();return "No referrer";}}

总结

  • 通过反射的方式reflectGetReferrer()获取到的mReferrer,是调用者的包名,目前来看是可靠的,但是需要在Android5.1(Api level 22)以及之后才能用。

  • getCallingPackage()getCallingActivity()只有在startActivityForResult()的时候才可以得到调用者的包名。

  • Activity的getReferrer()是不可靠的,因为调用者可以自己设置referrer的值。所以不能依赖此值来判断调用者。

  • Binder.getCallingUid()Binder.getCallingPid()一般用在同步调用中,在这几个情况中并不适用。

如何在Activity中获取调用者 -- getReferrer()相关推荐

  1. 关于Activity的getReferrer():如何在Activity中获取调用者?

    http://blog.csdn.net/u013553529/article/details/53856800 关于Activity的getReferrer()之一:如何在Activity中获取调用 ...

  2. java+script+当前日期_如何在JavaScript中获取当前日期?

    如何在JavaScript中获取当前日期? #1楼 您可以使用扩展了 Date对象的Date.js库,从而可以使用.today()方法. #2楼 如果您想对日期格式进行更多的粒度控制,我强烈建议您查看 ...

  3. 如何在PHP中获取客户端IP地址[重复]

    本文翻译自:How to get the client IP address in PHP [duplicate] This question already has an answer here: ...

  4. 如何在JavaScript中获取时间戳

    如何在JavaScript中获取时间戳 +运算符 我们可以使用+运算符将日期对象直接转换为UNIX时间戳. 例如,我们可以这样写: +new Date() +日期对象之前操作者触发valueOf的方法 ...

  5. 【Android】12.3 在当前Activity中获取另一个Activity的返回值

    分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 在上一节的示例中,通过StartActivity(Intent)方法启动另一个Activity后,这两个Activ ...

  6. java如何实取随机数_java - 如何在Kotlin中获取随机数?

    java - 如何在Kotlin中获取随机数? 可以在2个参数之间返回随机整数的通用方法,如ruby,可以使用rand(0..n). 有什么建议吗? 16个解决方案 208 votes 我的建议是In ...

  7. php mysql 到表最后_如何在PHP中获取MySQL表的最后插入ID?

    如何在PHP中获取MySQL表的最后插入ID? 我有一张表,经常插入新数据. 我需要获取表格的最后一个ID. 我怎样才能做到这一点? 它类似于SELECT MAX(id) FROM table吗? g ...

  8. 如何在JavaScript中获取字符串数组的字符串?

    本文翻译自:How do you get a string to a character array in JavaScript? How do you get a string to a chara ...

  9. java文件中获取创建日期_如何在Java中获取文件的上次修改日期

    java文件中获取创建日期 Sometimes we need to get the file last modified date in Java, usually for listeners li ...

最新文章

  1. KubeSphere安装Mysql5.7
  2. linux删除文件后,空间未释放的一种情况,使用lsof查看
  3. 一个Java工程师的入门级Linux命令集
  4. 大学期末考试SSH试题四
  5. SAP UI5 应用开发教程之三十五 - 如何把本地开发的 SAP UI5 应用部署到 ABAP 服务器上
  6. python 反复访问迭代器iter,反复使用next
  7. int默认值为0,Integer默认值为null
  8. linux搭建python运行环境_centos运行.py centos5.5下搭建python开发运行环境 - Linux - 服务器之家...
  9. spark的python开发安装方式,最简单的方式来安装Python依赖关系的Spark执行器节点?...
  10. 自动更新统计信息的阀值——人为更新统计信息的重要性
  11. Centos7安装32位库用来安装32位软件程序
  12. 学习使用DCMTK工具
  13. Cameralink光端机
  14. Docker 容器的随机命名
  15. c#(WinForm)绘制两个圆的内公切线
  16. 计算机毕设项目 python微信公众平台机器人
  17. ES6最通俗易懂的超重点保姆级笔记!女朋友看了都流泪的学习秘籍!没有一句废话,全部都是满满干货!
  18. Ardunio测试817光电耦合交流电过零检测模块
  19. 结构体与动态内存(5.11)
  20. 细分市场或成为OA产品同质化的救星|企服三会系列报道

热门文章

  1. 蚌埠经贸学校98计算机一班,蚌埠的科技贸易学校
  2. 【已解决】Html Webpack Plugin Error;html-withimg-loader无法正常解析html内的img
  3. 大剧透-逐浪字库设计师展现卓越书法功底
  4. 跑马灯效果影响EditText的焦点
  5. 真·富文本编辑器的演进之路
  6. 中小学教师计算机应用能力提升,【四川省中小学教师信息技术应用能力提升工程2.0】_四川省中小学教师信息技术应用能力提升工程_四川省中小学教师信息技术应用能力提升工程...
  7. 绞车拆装实训报告_机电一体化实习报告
  8. 【Python 教程】list 列表遍历的 4 种方法
  9. 怎么python编程excel_Excel 如何在excel中运行Python代码?-ExcelVBA程序开发-ExcelHome技术论坛 -...
  10. 微信小程序 各类效果(视频)