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

如何在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,作为referrer
        Uri referrer = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
        if (referrer != null) {
            return referrer;
        }
        // 如果之前没有获取到,则从intent的Intent.EXTRA_REFERRER_NAME数据获取,并转换成Uri
        String 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()一般用在同步调用中,在这几个情况中并不适用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容