Skip to content

Commit 4572cb9

Browse files
committed
Revert Kotlin conversion
1 parent 2ddfe8e commit 4572cb9

3 files changed

Lines changed: 189 additions & 144 deletions

File tree

.github/workflows/pull-request.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ name: "Build and Test"
22

33
on: [ push, workflow_dispatch, pull_request ]
44

5-
jobs:
5+
concurrency:
6+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
7+
cancel-in-progress: true
68

9+
jobs:
710
instrumented-tests:
811
name: "Instrumented Tests"
912
timeout-minutes: 30
@@ -220,3 +223,19 @@ jobs:
220223
name: "Save PR Number for Dependabot Automerge"
221224
needs: [ instrumented-tests, instrumented-orchestrator-tests, unit-tests, lint-checks, kotlin-lint-checks, kit-compatibility-test ]
222225
uses: mParticle/mparticle-workflows/.github/workflows/dependabot-save-pr-number.yml@main
226+
227+
pr-notify:
228+
if: >
229+
github.event_name == 'pull_request' &&
230+
github.event.pull_request.draft == false
231+
needs:
232+
- instrumented-tests
233+
- unit-tests
234+
- lint-checks
235+
- kotlin-lint-checks
236+
- security-checks
237+
name: Notify GChat
238+
uses: ROKT/rokt-workflows/.github/workflows/oss_pr_opened_notification.yml@main
239+
secrets:
240+
gchat_webhook: ${{ secrets.GCHAT_PRS_WEBHOOK }}
241+
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package com.mparticle;
2+
3+
import android.content.Context;
4+
import android.content.SharedPreferences;
5+
import android.os.Looper;
6+
7+
import androidx.annotation.NonNull;
8+
import androidx.annotation.Nullable;
9+
10+
import com.mparticle.internal.Constants;
11+
import com.mparticle.internal.Logger;
12+
13+
import java.lang.reflect.Method;
14+
import java.lang.reflect.Proxy;
15+
16+
/**
17+
* Helper class to fetch install referrer via reflection.
18+
*
19+
* To test the install referrer functionality:
20+
* 1. Set test application `applicationId` to a real app's Play Store package name, e.g. "com.medium.reader".
21+
*
22+
* 2. Ensure the app is fully uninstalled from the test device:
23+
* `adb uninstall com.medium.reader`
24+
*
25+
* 3. Broadcast the test referrer to the Play Store. This will open the Play Store app:
26+
* `adb shell "am start -a android.intent.action.VIEW -d 'https://play.google.com/store/apps/details?id=com.medium.reader&referrer=utm_source%3Dgoogle%26utm_medium%3Dcpc%26utm_term%3Drunning%252Bshoes%26utm_content%3Dcontent%26utm_campaign%3Dpromo'"`
27+
*
28+
* 4. Install the debug version of your test app.
29+
*
30+
* 5. Launch the app and check the logs for the referrer:
31+
* `adb logcat -d | grep 'Install Referrer received'`
32+
*
33+
* 6. Verify the referrer is logged in the test app's logs by checking for the utm_* parameters passed in during step 3.
34+
* e.g. `Install Referrer received: utm_source=google&utm_medium=cpc&utm_term=running%2Bshoes&utm_content=content&utm_campaign=promo`
35+
*
36+
* @see <a href="https://developer.android.com/reference/com/android/installreferrer/api/InstallReferrerClient">InstallReferrerClient</a>
37+
* @see <a href="https://medium.com/@madicdjordje/how-to-test-the-play-store-install-referrer-api-78a63d59945b">How to Test the Play Store Install Referrer API</a>
38+
*/
39+
public final class InstallReferrerHelper {
40+
41+
private static final String INSTALL_REFERRER_CLIENT_CLASS = "com.android.installreferrer.api.InstallReferrerClient";
42+
private static final String INSTALL_REFERRER_STATE_LISTENER_CLASS = "com.android.installreferrer.api.InstallReferrerStateListener";
43+
private static final String REFERRER_DETAILS_CLASS = "com.android.installreferrer.api.ReferrerDetails";
44+
45+
private InstallReferrerHelper() {
46+
//prevent instantiation
47+
}
48+
49+
@Nullable
50+
@SuppressWarnings("ConstantConditions")
51+
public static String getInstallReferrer(@NonNull final Context context) {
52+
if (context == null) {
53+
return null;
54+
}
55+
return context.getSharedPreferences(Constants.PREFS_FILE, 0).getString(Constants.PrefKeys.INSTALL_REFERRER, null);
56+
}
57+
58+
@SuppressWarnings("ConstantConditions")
59+
public static void setInstallReferrer(@NonNull final Context context, @Nullable final String referrer) {
60+
if (context != null) {
61+
final SharedPreferences preferences = context.getSharedPreferences(Constants.PREFS_FILE, Context.MODE_PRIVATE);
62+
preferences.edit().putString(Constants.PrefKeys.INSTALL_REFERRER, referrer).apply();
63+
final MParticle instance = MParticle.getInstance();
64+
if (instance != null) {
65+
instance.installReferrerUpdated();
66+
}
67+
}
68+
}
69+
70+
public static void fetchInstallReferrer(@NonNull final Context context, @NonNull final InstallReferrerCallback callback) {
71+
if (InstallReferrerHelper.getInstallReferrer(context) != null) {
72+
return;
73+
}
74+
75+
final Runnable runnable = () -> {
76+
try {
77+
final Class<?> clientClass = Class.forName(INSTALL_REFERRER_CLIENT_CLASS);
78+
final Class<?> listenerClass = Class.forName(INSTALL_REFERRER_STATE_LISTENER_CLASS);
79+
final Class<?> referrerDetailsClass = Class.forName(REFERRER_DETAILS_CLASS);
80+
81+
final Object builder = clientClass.getMethod("newBuilder", Context.class).invoke(null, context);
82+
if (builder == null) {
83+
Logger.warning("InstallReferrerClient.newBuilder() returned null");
84+
callback.onFailed();
85+
return;
86+
}
87+
88+
final Object builtClient = builder.getClass().getMethod("build").invoke(builder);
89+
final Object listener = Proxy.newProxyInstance(
90+
listenerClass.getClassLoader(),
91+
new Class[]{listenerClass},
92+
(proxy, method, args) -> {
93+
final String methodName = method.getName();
94+
95+
switch (methodName) {
96+
case "equals": return proxy == args[0];
97+
case "hashCode": return System.identityHashCode(proxy);
98+
case "toString": return "InstallReferrerListenerProxy";
99+
}
100+
101+
if ("onInstallReferrerSetupFinished".equals(methodName) && args != null && args.length > 0) {
102+
final int responseCode = (Integer) args[0];
103+
final int INSTALL_REFERRER_RESPONSE_OK = 0;
104+
105+
if (responseCode == INSTALL_REFERRER_RESPONSE_OK) {
106+
try {
107+
final Object referrerDetails = clientClass.getMethod("getInstallReferrer").invoke(builtClient);
108+
if (referrerDetails != null) {
109+
final String referrerUrl = (String) referrerDetailsClass.getMethod("getInstallReferrer").invoke(referrerDetails);
110+
Logger.debug("Install Referrer received: " + referrerUrl);
111+
callback.onReceived(referrerUrl);
112+
} else {
113+
callback.onFailed();
114+
}
115+
clientClass.getMethod("endConnection").invoke(builtClient);
116+
} catch (final Exception e) {
117+
Logger.warning("Reflection error getting install referrer: " + e.getMessage());
118+
callback.onFailed();
119+
}
120+
} else {
121+
callback.onFailed();
122+
}
123+
}
124+
125+
return null;
126+
});
127+
128+
Method startConnectionMethod = null;
129+
for (final Method method : clientClass.getMethods()) {
130+
if (method.getName().equals("startConnection") && method.getParameterTypes().length == 1) {
131+
startConnectionMethod = method;
132+
break;
133+
}
134+
}
135+
136+
if (startConnectionMethod == null) {
137+
Logger.warning("Could not find startConnection method via reflection");
138+
callback.onFailed();
139+
return;
140+
}
141+
142+
startConnectionMethod.invoke(builtClient, listener);
143+
144+
} catch (final ClassNotFoundException e) {
145+
Logger.warning("InstallReferrer library not present");
146+
callback.onFailed();
147+
} catch (final Exception e) {
148+
Logger.error("Error fetching install referrer: " + e.getMessage());
149+
callback.onFailed();
150+
}
151+
};
152+
153+
try {
154+
if (Looper.getMainLooper() == Looper.myLooper()) {
155+
new Thread(runnable).start();
156+
} else {
157+
runnable.run();
158+
}
159+
} catch (final Exception e) {
160+
callback.onFailed();
161+
}
162+
}
163+
164+
public interface InstallReferrerCallback {
165+
void onReceived(@Nullable String installReferrer);
166+
167+
void onFailed();
168+
}
169+
}

android-core/src/main/kotlin/com/mparticle/InstallReferrerHelper.kt

Lines changed: 0 additions & 143 deletions
This file was deleted.

0 commit comments

Comments
 (0)