pedronveloso
pedronveloso

Reputation: 965

get CORRECT referrer application on deep linking

I'm looking to get stats on where my application is being opened from. I started of by looking at this example:

https://github.com/googlecodelabs/deeplink-referrer/blob/master/end/app/src/main/java/com/google/samples/search/recipe_app/client/AnalyticsApplication.java

Which leverages the method getReferrer() from Activity. Now what I'm seeing when debugging my application and opening a result from the Google Search application is that this method ALWAYS gets me the http link of the result, but it never gives me the information that the app used by the user was Google Search. I know that this information is delivered to the application, because if I inspect the Activity I can see the mReferrer property contains the package name of the caller app, exactly what I was looking for! BUT, there is no way to access said property, and the only place that it is used is on the method getReferrer(). Now looking at that method, this is what is inside, from the Activity class:

 /**
 * Return information about who launched this activity.  If the launching Intent
 * contains an {@link android.content.Intent#EXTRA_REFERRER Intent.EXTRA_REFERRER},
 * that will be returned as-is; otherwise, if known, an
 * {@link Intent#URI_ANDROID_APP_SCHEME android-app:} referrer URI containing the
 * package name that started the Intent will be returned.  This may return null if no
 * referrer can be identified -- it is neither explicitly specified, nor is it known which
 * application package was involved.
 *
 * <p>If called while inside the handling of {@link #onNewIntent}, this function will
 * return the referrer that submitted that new intent to the activity.  Otherwise, it
 * always returns the referrer of the original Intent.</p>
 *
 * <p>Note that this is <em>not</em> a security feature -- you can not trust the
 * referrer information, applications can spoof it.</p>
 */
@Nullable
public Uri getReferrer() {
    Intent intent = getIntent();
    try {
        Uri referrer = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
        if (referrer != null) {
            return referrer;
        }
        String referrerName = intent.getStringExtra(Intent.EXTRA_REFERRER_NAME);
        if (referrerName != null) {
            return Uri.parse(referrerName);
        }
    } catch (BadParcelableException e) {
        Log.w(TAG, "Cannot read referrer from intent;"
                + " intent extras contain unknown custom Parcelable objects");
    }
    if (mReferrer != null) {
        return new Uri.Builder().scheme("android-app").authority(mReferrer).build();
    }
    return null;
}

As you can see, priority is given to the Intent.EXTRA_REFERRER, which will always be there, so the last part that used mReferrer can never be used.

Is there any way the caller package name can be retrieved ?

Upvotes: 3

Views: 4069

Answers (2)

Phillen
Phillen

Reputation: 336

In Kotlin you can use

referrer?.authority

and it will return the caller packagename

Upvotes: 0

pedronveloso
pedronveloso

Reputation: 965

Well, just figured out a way to do it myself. Sharing here in case anyone goes trought the same. In essence, looking at how getReferrer() works, this will get me the package name:

        // Backup referrer info and remove it temporarily.
        Uri extraReferrerBackup = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
        String extraReferrerNameBackup = getIntent().getStringExtra(Intent.EXTRA_REFERRER_NAME);
        getIntent().removeExtra(Intent.EXTRA_REFERRER);
        getIntent().removeExtra(Intent.EXTRA_REFERRER_NAME);

        // Get the app referrer.
        Uri referrer = getReferrer();

        // Restore previous http referrer info.
        getIntent().putExtra(Intent.EXTRA_REFERRER, extraReferrerBackup);
        getIntent().putExtra(Intent.EXTRA_REFERRER_NAME, extraReferrerNameBackup);

Upvotes: 4

Related Questions