{
15 | val task = BaseAudienceTask()
16 | if (featureFlagEnabled) {
17 | CoroutineScope(Dispatchers.IO).launch {
18 | mApiClient.fetchUserAudience(task, mpId)
19 | }
20 | } else {
21 | task.setFailed(
22 | AudienceResponse(
23 | IdentityApi.UNKNOWN_ERROR,
24 | "Audience API call forbidden: Audience API is not enabled for your account"
25 | )
26 | )
27 | }
28 | return task
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/database/MPDatabase.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.database;
2 |
3 | import android.content.ContentValues;
4 | import android.database.Cursor;
5 |
6 | public interface MPDatabase {
7 |
8 | long insert(String table, String nullColumnHack, ContentValues contentValues);
9 |
10 | Cursor query(String table, String[] columns, String selection,
11 | String[] selectionArgs, String groupBy, String having,
12 | String orderBy, String limit);
13 |
14 | Cursor query(String table, String[] columns, String selection,
15 | String[] selectionArgs, String groupBy, String having,
16 | String orderBy);
17 |
18 | Cursor rawQuery(String query, String... selectionArgs);
19 |
20 | int delete(String table, String whereClause, String[] whereArgs);
21 |
22 | void beginTransaction();
23 |
24 | void setTransactionSuccessful();
25 |
26 | void endTransaction();
27 |
28 | int update(String tableName, ContentValues contentValues, String s, String[] strings);
29 | }
30 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/database/services/SQLiteOpenHelperWrapper.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.database.services;
2 |
3 | import android.database.sqlite.SQLiteDatabase;
4 |
5 | public interface SQLiteOpenHelperWrapper {
6 |
7 | void onCreate(SQLiteDatabase database);
8 |
9 | void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion);
10 |
11 | void onDowngrade(SQLiteDatabase database, int oldVersion, int newVersion);
12 | }
13 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/database/tables/BreadcrumbTable.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.database.tables;
2 |
3 | import android.provider.BaseColumns;
4 |
5 | public class BreadcrumbTable extends MpIdDependentTable {
6 |
7 | @Override
8 | public String getTableName() {
9 | return BreadcrumbTableColumns.TABLE_NAME;
10 | }
11 |
12 | protected interface BreadcrumbTableColumns {
13 | String TABLE_NAME = "breadcrumbs";
14 | String SESSION_ID = "session_id";
15 | String API_KEY = "api_key";
16 | String MESSAGE = "message";
17 | String CREATED_AT = "breadcrumb_time";
18 | String CF_UUID = "cfuuid";
19 | String MP_ID = MpIdDependentTable.MP_ID;
20 | }
21 |
22 | static final String CREATE_BREADCRUMBS_DDL =
23 | "CREATE TABLE IF NOT EXISTS " + BreadcrumbTableColumns.TABLE_NAME + " (" + BaseColumns._ID +
24 | " INTEGER PRIMARY KEY AUTOINCREMENT, " +
25 | BreadcrumbTableColumns.SESSION_ID + " STRING NOT NULL, " +
26 | BreadcrumbTableColumns.API_KEY + " STRING NOT NULL, " +
27 | BreadcrumbTableColumns.MESSAGE + " TEXT, " +
28 | BreadcrumbTableColumns.CREATED_AT + " INTEGER NOT NULL, " +
29 | BreadcrumbTableColumns.CF_UUID + " TEXT, " +
30 | BreadcrumbTableColumns.MP_ID + " INTEGER" +
31 | ");";
32 | }
33 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/database/tables/MessageTable.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.database.tables;
2 |
3 | import android.provider.BaseColumns;
4 |
5 | public class MessageTable extends MpIdDependentTable {
6 |
7 | public static final String ADD_DATAPLAN_VERSION_COLUMN = "ALTER TABLE " + MessageTableColumns.TABLE_NAME +
8 | " ADD COLUMN " + MessageTableColumns.DATAPLAN_VERSION + " NUMBER";
9 | public static final String ADD_DATAPLAN_ID_COLUMN = "ALTER TABLE " + MessageTableColumns.TABLE_NAME +
10 | " ADD COLUMN " + MessageTableColumns.DATAPLAN_ID + " TEXT";
11 |
12 | @Override
13 | public String getTableName() {
14 | return MessageTableColumns.TABLE_NAME;
15 | }
16 |
17 | public interface MessageTableColumns extends BaseColumns {
18 | String TABLE_NAME = "messages";
19 | String SESSION_ID = "session_id";
20 | String API_KEY = "api_key";
21 | String MESSAGE = "message";
22 | String STATUS = "upload_status";
23 | String CREATED_AT = "message_time";
24 | String MESSAGE_TYPE = "message_type";
25 | String CF_UUID = "cfuuid";
26 | String MP_ID = MpIdDependentTable.MP_ID;
27 | String DATAPLAN_VERSION = "dataplan_version";
28 | String DATAPLAN_ID = "dataplan_id";
29 | }
30 |
31 | static final String CREATE_MESSAGES_DDL =
32 | "CREATE TABLE IF NOT EXISTS " + MessageTableColumns.TABLE_NAME + " (" + BaseColumns._ID +
33 | " INTEGER PRIMARY KEY AUTOINCREMENT, " +
34 | MessageTableColumns.SESSION_ID + " STRING NOT NULL, " +
35 | MessageTableColumns.API_KEY + " STRING NOT NULL, " +
36 | MessageTableColumns.MESSAGE + " TEXT, " +
37 | MessageTableColumns.STATUS + " INTEGER, " +
38 | MessageTableColumns.CREATED_AT + " INTEGER NOT NULL, " +
39 | MessageTableColumns.MESSAGE_TYPE + " TEXT, " +
40 | MessageTableColumns.CF_UUID + " TEXT, " +
41 | MessageTableColumns.MP_ID + " INTEGER, " +
42 | MessageTableColumns.DATAPLAN_ID + " TEXT," +
43 | MessageTableColumns.DATAPLAN_VERSION + " INTEGER" +
44 | ");";
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/database/tables/MpIdDependentTable.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.database.tables;
2 |
3 | import android.content.ContentValues;
4 |
5 | import com.mparticle.internal.database.MPDatabase;
6 |
7 | public abstract class MpIdDependentTable {
8 | public static final String MP_ID = "mp_id";
9 |
10 | public abstract String getTableName();
11 |
12 | public void updateMpId(MPDatabase database, long oldMpId, long newMpId) {
13 | ContentValues contentValues = new ContentValues();
14 | contentValues.put(MP_ID, newMpId);
15 | database.update(getTableName(), contentValues, MP_ID + " = ?", new String[]{String.valueOf(oldMpId)});
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/database/tables/ReportingTable.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.database.tables;
2 |
3 | import android.provider.BaseColumns;
4 |
5 | public class ReportingTable extends MpIdDependentTable {
6 |
7 | @Override
8 | public String getTableName() {
9 | return ReportingTableColumns.TABLE_NAME;
10 | }
11 |
12 | protected interface ReportingTableColumns extends BaseColumns {
13 | String CREATED_AT = "report_time";
14 | String MODULE_ID = "module_id";
15 | String TABLE_NAME = "reporting";
16 | String MESSAGE = "message";
17 | String SESSION_ID = "session_id";
18 | String MP_ID = MpIdDependentTable.MP_ID;
19 | }
20 |
21 | static final String CREATE_REPORTING_DDL =
22 | "CREATE TABLE IF NOT EXISTS " + ReportingTableColumns.TABLE_NAME + " (" + BaseColumns._ID +
23 | " INTEGER PRIMARY KEY AUTOINCREMENT, " +
24 | ReportingTableColumns.MODULE_ID + " INTEGER NOT NULL, " +
25 | ReportingTableColumns.MESSAGE + " TEXT NOT NULL, " +
26 | ReportingTableColumns.SESSION_ID + " STRING NOT NULL, " +
27 | ReportingTableColumns.CREATED_AT + " INTEGER NOT NULL, " +
28 | ReportingTableColumns.MP_ID + " INTEGER" +
29 | ");";
30 |
31 | static final String REPORTING_ADD_SESSION_ID_COLUMN = "ALTER TABLE " + ReportingTableColumns.TABLE_NAME +
32 | " ADD COLUMN " + ReportingTableColumns.SESSION_ID + " STRING";
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/database/tables/UploadTable.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.database.tables;
2 |
3 | import android.provider.BaseColumns;
4 |
5 | public class UploadTable {
6 |
7 | public static final String UPLOAD_REQUEST = "0";
8 | public static final String ALIAS_REQUEST = "1";
9 |
10 | protected interface UploadTableColumns extends BaseColumns {
11 | String TABLE_NAME = "uploads";
12 | String API_KEY = "api_key";
13 | String MESSAGE = "message";
14 | String CREATED_AT = "message_time";
15 | /**
16 | * This column, previously unused as CFUUID, has been re-purposed for REQUEST_TYPE
17 | * to avoid a schema change.
18 | */
19 | String REQUEST_TYPE = "cfuuid";
20 | String SESSION_ID = "session_id";
21 | String UPLOAD_SETTINGS = "upload_settings";
22 | }
23 |
24 |
25 | static final String CREATE_UPLOADS_DDL =
26 | "CREATE TABLE IF NOT EXISTS " + UploadTableColumns.TABLE_NAME + " (" + BaseColumns._ID +
27 | " INTEGER PRIMARY KEY AUTOINCREMENT, " +
28 | UploadTableColumns.API_KEY + " STRING NOT NULL, " +
29 | UploadTableColumns.MESSAGE + " TEXT, " +
30 | UploadTableColumns.CREATED_AT + " INTEGER NOT NULL, " +
31 | UploadTableColumns.REQUEST_TYPE + " TEXT, " +
32 | UploadTableColumns.SESSION_ID + " TEXT, " +
33 | UploadTableColumns.UPLOAD_SETTINGS + " TEXT" +
34 | ");";
35 |
36 | static final String UPLOAD_ADD_UPLOAD_SETTINGS_COLUMN = "ALTER TABLE " + UploadTableColumns.TABLE_NAME +
37 | " ADD COLUMN " + UploadTableColumns.UPLOAD_SETTINGS + " TEXT";
38 | }
39 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/database/tables/UserAttributesTable.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.database.tables;
2 |
3 | import android.provider.BaseColumns;
4 |
5 | public class UserAttributesTable extends MpIdDependentTable {
6 |
7 | @Override
8 | public String getTableName() {
9 | return UserAttributesTableColumns.TABLE_NAME;
10 | }
11 |
12 | protected interface UserAttributesTableColumns {
13 | String TABLE_NAME = "attributes";
14 | String ATTRIBUTE_KEY = "attribute_key";
15 | String ATTRIBUTE_VALUE = "attribute_value";
16 | String IS_LIST = "is_list";
17 | String CREATED_AT = "created_time";
18 | String MP_ID = MpIdDependentTable.MP_ID;
19 | }
20 |
21 | static final String CREATE_USER_ATTRIBUTES_DDL =
22 | "CREATE TABLE IF NOT EXISTS " + UserAttributesTableColumns.TABLE_NAME + " (" + BaseColumns._ID +
23 | " INTEGER PRIMARY KEY AUTOINCREMENT, " +
24 | UserAttributesTableColumns.ATTRIBUTE_KEY + " COLLATE NOCASE NOT NULL, " +
25 | UserAttributesTableColumns.ATTRIBUTE_VALUE + " TEXT, " +
26 | UserAttributesTableColumns.IS_LIST + " INTEGER NOT NULL, " +
27 | UserAttributesTableColumns.CREATED_AT + " INTEGER NOT NULL, " +
28 | UserAttributesTableColumns.MP_ID + " INTEGER" +
29 | ");";
30 | }
31 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/messages/MPEventMessage.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.messages;
2 |
3 | import android.location.Location;
4 |
5 | import androidx.annotation.Nullable;
6 |
7 | import com.mparticle.MParticle;
8 | import com.mparticle.internal.Constants;
9 | import com.mparticle.internal.InternalSession;
10 |
11 | import org.json.JSONException;
12 |
13 | public class MPEventMessage extends BaseMPMessage {
14 |
15 | protected MPEventMessage(Builder builder, InternalSession session, @Nullable Location location, long mpId) throws JSONException {
16 | super(builder, session, location, mpId);
17 | }
18 |
19 | public static class Builder extends BaseMPMessageBuilder {
20 |
21 | public Builder(String messageType) {
22 | super(messageType);
23 | }
24 |
25 | public BaseMPMessageBuilder customEventType(MParticle.EventType eventType) {
26 | try {
27 | put(Constants.MessageKey.EVENT_TYPE, eventType);
28 | } catch (JSONException e) {
29 | e.printStackTrace();
30 | }
31 | return this;
32 | }
33 |
34 | @Override
35 | public BaseMPMessage build(InternalSession session, Location location, long mpId) throws JSONException {
36 | return new MPEventMessage(this, session, location, mpId);
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/internal/package-info.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal;
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/media/MPMediaAPI.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.media;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 |
8 | import java.util.concurrent.atomic.AtomicBoolean;
9 |
10 | /**
11 | * Utility class to interact with the mParticle Media APIs. Do not directly instantiate this.
12 | *
13 | * @see com.mparticle.MParticle#Media()
14 | */
15 | public class MPMediaAPI {
16 | private final MediaCallbacks mCallbacks;
17 | private final Context mContext;
18 | private AtomicBoolean mAudioPlaying = new AtomicBoolean(false);
19 |
20 | private MPMediaAPI() {
21 | mContext = null;
22 | mCallbacks = null;
23 | }
24 |
25 | public MPMediaAPI(@Nullable Context context, @NonNull MediaCallbacks callbacks) {
26 | mContext = context;
27 | mCallbacks = callbacks;
28 | }
29 |
30 | /**
31 | * Use this method to inform the SDK that there is audio playing. In the case where a
32 | * user navigates away from your app, but your app is playing music in the background,
33 | * using this method will ensure that the mParticle SDK does not end the user's session prematurely.
34 | * A user's session will be considered active as long as audio is playing, so be sure to use this method
35 | * both to signal when audio starts, as well as when it pauses or stops.
36 | *
37 | * @param playing Is your app currently playing music for the user.
38 | */
39 | public void setAudioPlaying(boolean playing) {
40 | mAudioPlaying.set(playing);
41 | if (playing) {
42 | mCallbacks.onAudioPlaying();
43 | } else {
44 | mCallbacks.onAudioStopped();
45 | }
46 | }
47 |
48 | public boolean getAudioPlaying() {
49 | return mAudioPlaying.get();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/media/MediaCallbacks.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.media;
2 |
3 | /**
4 | *
5 | */
6 | public interface MediaCallbacks {
7 | public void onAudioPlaying();
8 |
9 | public void onAudioStopped();
10 | }
11 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/media/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Package containing the mParticle Media APIs.
3 | */
4 | package com.mparticle.media;
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/messaging/InstanceIdService.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.messaging;
2 |
3 | import com.google.firebase.messaging.FirebaseMessagingService;
4 | import com.mparticle.internal.Logger;
5 | import com.mparticle.internal.PushRegistrationHelper;
6 |
7 | /**
8 | * mParticle implementation of InstanceIDListenerService. In order to support push notifications, you must
9 | * include this Service within your app's AndroidManifest.xml with an intent-filter for 'com.google.android.gms.iid.InstanceID'.
10 | */
11 | public class InstanceIdService extends FirebaseMessagingService {
12 |
13 | @Override
14 | public void onNewToken(String s) {
15 | try {
16 | PushRegistrationHelper.requestInstanceId(getApplicationContext());
17 | } catch (Exception e) {
18 | Logger.error("Error refreshing Instance ID: " + e.getMessage());
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/messaging/MPMessagingRouter.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.messaging;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 |
6 | import com.mparticle.MPServiceUtil;
7 |
8 | public class MPMessagingRouter {
9 | /**
10 | * Parses the incoming intent and delegates functionality to the given {@code callback} if appropriate. This implementation checks for
11 | * MParticle-specific actions and will not handle messages outside of that scope. MParticle actions can be found in
12 | * {@link MPMessagingAPI} {@code BROADCAST_*} constants.
13 | *
14 | * @param context
15 | * @param intent
16 | * @param callback
17 | * @return {@code true} if the {@link Intent} was handled by MParticle
18 | */
19 | public static boolean onReceive(Context context, Intent intent, PushAnalyticsReceiverCallback callback) {
20 | if (MPMessagingAPI.BROADCAST_NOTIFICATION_TAPPED.equalsIgnoreCase(intent.getAction())) {
21 | ProviderCloudMessage message = intent.getParcelableExtra(MPMessagingAPI.CLOUD_MESSAGE_EXTRA);
22 | if (!callback.onNotificationTapped(message)) {
23 | intent.putExtra(MPMessagingAPI.CLOUD_MESSAGE_EXTRA, message);
24 | MPServiceUtil.runIntentInService(context, intent);
25 | }
26 | return true;
27 | } else if (MPMessagingAPI.BROADCAST_NOTIFICATION_RECEIVED.equalsIgnoreCase(intent.getAction())) {
28 | ProviderCloudMessage message = intent.getParcelableExtra(MPMessagingAPI.CLOUD_MESSAGE_EXTRA);
29 | if (!callback.onNotificationReceived(message)) {
30 | intent.putExtra(MPMessagingAPI.CLOUD_MESSAGE_EXTRA, message);
31 | MPServiceUtil.runIntentInService(context, intent);
32 | }
33 | return true;
34 | }
35 |
36 | return false;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/messaging/MessagingConfigCallbacks.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.messaging;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | public interface MessagingConfigCallbacks {
6 | void onInstanceIdRegistered(@Nullable String instanceId);
7 | }
8 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/messaging/PushAnalyticsReceiver.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.messaging;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | /**
8 | * BroadcastReceiver
to be used to listen for, manipulate, and react to FCM notifications.
9 | *
10 | * In order to use this class:
11 | *
12 | * 1. Create your own class which extends this one, for example MyPushReceiver.java
13 | * 2. Add the following to your AndroidManifest.xml
, replacing YOURPACKAGENAME
and the name of your BroadcastReceiver
:
14 | *
15 | * {@code
16 | *
17 | *
18 | *
19 | *
20 | *
21 | * }
22 | *
23 | * @see #onNotificationReceived(ProviderCloudMessage)
24 | * @see #onNotificationTapped(ProviderCloudMessage)
25 | */
26 | public class PushAnalyticsReceiver extends BroadcastReceiver implements PushAnalyticsReceiverCallback {
27 |
28 | @Override
29 | public final void onReceive(Context context, Intent intent) {
30 | MPMessagingRouter.onReceive(context, intent, this);
31 | }
32 |
33 | @Override
34 | public boolean onNotificationReceived(ProviderCloudMessage message) {
35 | return false;
36 | }
37 |
38 | @Override
39 | public boolean onNotificationTapped(ProviderCloudMessage message) {
40 | return false;
41 | }
42 | }
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/messaging/PushAnalyticsReceiverCallback.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.messaging;
2 |
3 | public interface PushAnalyticsReceiverCallback {
4 | /**
5 | * Override this method to listen for when a notification has been received.
6 | *
7 | * @param message The message that was received. Depending on the push provider
8 | * @return True if you would like to handle this notification, False if you would like the mParticle to generate and show a {@link android.app.Notification}.
9 | */
10 | boolean onNotificationReceived(ProviderCloudMessage message);
11 |
12 | /**
13 | * Override this method to listen for when a notification has been tapped or acted on.
14 | *
15 | * @param message The message that was tapped. Depending on the push provider
16 | * @return True if you would like to consume this tap/action, False if the mParticle SDK should attempt to handle it.
17 | */
18 | boolean onNotificationTapped(ProviderCloudMessage message);
19 | }
20 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/messaging/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Package containing the mParticle messaging and push APIs.
3 | */
4 | package com.mparticle.messaging;
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/networking/Certificate.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.mparticle.internal.Logger;
7 | import com.mparticle.internal.MPUtility;
8 |
9 | import org.json.JSONException;
10 | import org.json.JSONObject;
11 |
12 | public final class Certificate {
13 | private String alias;
14 | private String certificate;
15 |
16 | private Certificate(String alias, String certificate) {
17 | this.alias = alias;
18 | this.certificate = certificate;
19 | }
20 |
21 | @Nullable
22 | public static Certificate with(@NonNull String alias, @NonNull String certificate) {
23 | if (MPUtility.isEmpty(alias) || MPUtility.isEmpty(certificate)) {
24 | Logger.warning(String.format("Alias and Certificate values must both be non-empty strings. Unable to build certificate with Alias = %s and Certificate = %s.", alias, certificate));
25 | return null;
26 | }
27 | return new Certificate(alias, certificate);
28 | }
29 |
30 | @NonNull
31 | public String getAlias() {
32 | return alias;
33 | }
34 |
35 | @NonNull
36 | public String getCertificate() {
37 | return certificate;
38 | }
39 |
40 | static Certificate withCertificate(JSONObject jsonObject) {
41 | try {
42 | String alias = jsonObject.getString("alias");
43 | String certificate = jsonObject.getString("certificate");
44 | return new Certificate(alias, certificate);
45 | } catch (JSONException e) {
46 | e.printStackTrace();
47 | }
48 | return null;
49 | }
50 |
51 | @Override
52 | @NonNull
53 | public String toString() {
54 | return toJson().toString();
55 | }
56 |
57 | JSONObject toJson() {
58 | JSONObject jsonObject = new JSONObject();
59 | try {
60 | return new JSONObject()
61 | .put("alias", getAlias())
62 | .put("certificate", getCertificate());
63 | } catch (JSONException jse) {
64 | Logger.error(jse);
65 | }
66 | return jsonObject;
67 | }
68 | }
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/networking/MPConnection.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.io.OutputStream;
6 | import java.net.ProtocolException;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | import javax.net.ssl.SSLSocketFactory;
11 |
12 | public interface MPConnection {
13 | boolean isHttps();
14 |
15 |
16 | void setRequestMethod(String method) throws ProtocolException;
17 |
18 | void setDoOutput(Boolean doOutput);
19 |
20 | void setConnectTimeout(Integer timeout);
21 |
22 | void setReadTimeout(Integer readTimeout);
23 |
24 | void setRequestProperty(String key, String value);
25 |
26 | MPUrl getURL();
27 |
28 | String getRequestMethod();
29 |
30 | String getHeaderField(String key);
31 |
32 | Map> getHeaderFields();
33 |
34 | OutputStream getOutputStream() throws IOException;
35 |
36 | InputStream getInputStream() throws IOException;
37 |
38 | InputStream getErrorStream();
39 |
40 | int getResponseCode() throws IOException;
41 |
42 | String getResponseMessage() throws IOException;
43 |
44 | void setSSLSocketFactory(SSLSocketFactory factory);
45 |
46 | SSLSocketFactory getSSLSocketFactory();
47 | }
48 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/networking/MPUrl.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import java.io.IOException;
7 | import java.net.MalformedURLException;
8 |
9 | public abstract class MPUrl {
10 |
11 | private static UrlFactory mpUrlFactory = null;
12 | private MPUrl defaultUrl;
13 |
14 | static void setMPUrlFactory(UrlFactory urlConstructor) {
15 | mpUrlFactory = urlConstructor;
16 | }
17 |
18 | public static MPUrl getUrl(String url, @Nullable MPUrl defaultUrl) throws MalformedURLException {
19 | if (mpUrlFactory != null) {
20 | try {
21 | return mpUrlFactory.getInstance(url)
22 | .setDefaultUrl(defaultUrl);
23 | } catch (Exception ex) {
24 |
25 | }
26 | }
27 | return new MPUrlImpl(url)
28 | .setDefaultUrl(defaultUrl);
29 | }
30 |
31 | @Override
32 | public String toString() {
33 | return getFile();
34 | }
35 |
36 | public abstract MPConnection openConnection() throws IOException;
37 |
38 | public abstract String getFile();
39 |
40 | public abstract String getAuthority();
41 |
42 | public abstract String getPath();
43 |
44 | /**
45 | * returns an instance of the Default URL, if NetworkOptions is being used to override it. Otherwise,
46 | * a reference to itself will be returned
47 | *
48 | * @return an MPUrl instance with the the default URL
49 | */
50 | @NonNull
51 | public MPUrl getDefaultUrl() {
52 | if (defaultUrl != null) {
53 | return defaultUrl;
54 | } else {
55 | return this;
56 | }
57 | }
58 |
59 | MPUrl setDefaultUrl(@Nullable MPUrl url) {
60 | this.defaultUrl = url;
61 | return this;
62 | }
63 |
64 | interface UrlFactory {
65 | MPUrl getInstance(String url);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/networking/MPUrlImpl.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | import java.io.IOException;
4 | import java.net.HttpURLConnection;
5 | import java.net.MalformedURLException;
6 | import java.net.URL;
7 |
8 | class MPUrlImpl extends MPUrl {
9 | private URL url;
10 |
11 | MPUrlImpl(String url) throws MalformedURLException {
12 | this.url = new URL(url);
13 | }
14 |
15 | MPUrlImpl(URL url) {
16 | this.url = url;
17 | }
18 |
19 | @Override
20 | public MPConnection openConnection() throws IOException {
21 | return new MPConnectionImpl((HttpURLConnection) url.openConnection(), this);
22 | }
23 |
24 | @Override
25 | public String getFile() {
26 | return url.getFile();
27 | }
28 |
29 | @Override
30 | public String getAuthority() {
31 | return url.getAuthority();
32 | }
33 |
34 | @Override
35 | public String getPath() {
36 | return url.getPath();
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return url.toString();
42 | }
43 |
44 | @Override
45 | public boolean equals(Object obj) {
46 | if (obj instanceof MPUrlImpl) {
47 | return url.equals(((MPUrlImpl) obj).url);
48 | }
49 | return url.equals(obj);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/networking/MParticleBaseClient.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | public interface MParticleBaseClient {
4 | BaseNetworkConnection getRequestHandler();
5 |
6 | void setRequestHandler(BaseNetworkConnection handler);
7 | }
8 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The primary package for the mParticle SDK where most of the public APIs reside - start here.
3 | */
4 | package com.mparticle;
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/segmentation/Segment.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.segmentation;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import org.json.JSONArray;
7 | import org.json.JSONException;
8 |
9 | import java.util.Arrays;
10 |
11 | /**
12 | * This class represents a single Segment of which one or more users may be a member.
13 | */
14 | public class Segment {
15 | int id;
16 | String name;
17 | String[] endpoints;
18 |
19 | public Segment(int id, @NonNull String name, @NonNull String endpointBlob) {
20 | this.id = id;
21 | this.name = name;
22 | try {
23 | JSONArray endpointJson = new JSONArray(endpointBlob);
24 | endpoints = new String[endpointJson.length()];
25 | for (int i = 0; i < endpointJson.length(); i++) {
26 | endpoints[i] = endpointJson.getString(i);
27 | }
28 | } catch (JSONException jse) {
29 |
30 | }
31 |
32 | }
33 |
34 | /**
35 | * Retrieve the unique segment ID.
36 | *
37 | * @return an integer ID
38 | */
39 | public int getId() {
40 | return id;
41 | }
42 |
43 | /**
44 | * Retrieve the display name for this Segment, configured via the mParticle web console.
45 | *
46 | * @return
47 | */
48 | @Nullable
49 | public String getName() {
50 | return name;
51 | }
52 |
53 | /**
54 | * Retrieve the endpoint IDs to which this Segment is configured to forward.
55 | *
56 | * @return an array of IDs
57 | */
58 | @NonNull
59 | public String[] getEndpoints() {
60 | if (endpoints != null) {
61 | return endpoints;
62 | } else {
63 | return new String[]{};
64 | }
65 | }
66 |
67 | /**
68 | * Retrieve a readable summary of this Segment.
69 | *
70 | * @return Segment summary
71 | */
72 | @Override
73 | @NonNull
74 | public String toString() {
75 | return "Segment ID: " + id + ", " +
76 | "Name: " + name + ", " +
77 | "Endpoints: " + ((endpoints != null && endpoints.length > 0) ? Arrays.toString(endpoints) : "None specified.");
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/segmentation/SegmentListener.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.segmentation;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | /**
6 | * Use this callback interface to retrieve the current user's segment membership.
7 | */
8 | public interface SegmentListener {
9 | void onSegmentsRetrieved(@Nullable SegmentMembership segmentMembership);
10 | }
11 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/segmentation/SegmentMembership.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.segmentation;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import java.util.ArrayList;
6 |
7 | /**
8 | * This class is returned as response from a user segments call. It contains segment ids, expiration, and a flag indicating whether it is expired.
9 | */
10 | public class SegmentMembership {
11 | private ArrayList segments;
12 | StringBuilder list;
13 |
14 | public SegmentMembership(@NonNull ArrayList ids) {
15 | super();
16 | segments = ids;
17 | }
18 |
19 | /**
20 | * The list of user segment IDs.
21 | */
22 | @NonNull
23 | public ArrayList getSegments() {
24 | return segments;
25 | }
26 |
27 | /**
28 | * Returns a String with a comma separated list of user segment IDs.
29 | */
30 | @Override
31 | @NonNull
32 | public String toString() {
33 | return getCommaSeparatedIds();
34 | }
35 |
36 | /**
37 | * Returns a String with a comma separated list of user segment IDs.
38 | */
39 | @NonNull
40 | public String getCommaSeparatedIds() {
41 | if (list == null) {
42 | list = new StringBuilder();
43 |
44 | for (Segment segment : segments) {
45 | list.append(segment.getId());
46 | list.append(", ");
47 | }
48 | if (list.length() > 0) {
49 | list.delete(list.length() - 2, list.length());
50 | }
51 | }
52 | return list.toString();
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/android-core/src/main/java/com/mparticle/segmentation/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Package containing the mParticle Segmentation APIs.
3 | */
4 | package com.mparticle.segmentation;
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/TypedUserAttributeListener.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | interface TypedUserAttributeListener : UserAttributeListenerType {
4 | fun onUserAttributesReceived(
5 | userAttributes: Map,
6 | userAttributeLists: Map?>,
7 | mpid: Long
8 | )
9 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/UserAttributeListenerType.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | interface UserAttributeListenerType
4 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/WrapperSdk.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | enum class WrapperSdk(wrapperSdkId: Int, wrapperSdkName: String) {
4 | WrapperNone(0, "None"),
5 | WrapperSdkUnity(1, "Unity"),
6 | WrapperSdkReactNative(2, "React Native"),
7 | WrapperSdkCordova(3, "Cordova"),
8 | WrapperXamarin(4, "Xamarin"),
9 | WrapperFlutter(5, "Flutter");
10 | }
11 |
12 | /**
13 | * @param sdk represent the wrapper sdk. If not configured will be [WrapperSdk.WrapperNone]
14 | * @param version represents the configured version for the wrapper sdk. Will return null if
15 | * [WrapperSdk.WrapperNone] is set as the sdk wrapper
16 | */
17 | data class WrapperSdkVersion(val sdk: WrapperSdk, val version: String?)
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/audience/Audience.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.audience
2 |
3 | data class Audience(val audienceID:String)
4 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/audience/AudienceResponse.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.audience
2 |
3 | import com.mparticle.internal.Logger
4 | import org.json.JSONObject
5 |
6 | class AudienceResponse {
7 | private var code: Int = 0
8 | private var error: String? = null
9 | private var result: JSONObject? = null
10 | private var audienceList = ArrayList()
11 |
12 | constructor(httpCode: Int, errorMsg: String) {
13 | code = httpCode
14 | error = errorMsg
15 |
16 | }
17 |
18 | constructor(httpCode: Int, jsonObject: JSONObject) {
19 | code = httpCode
20 | result = jsonObject
21 | parseJsonObject(jsonObject)
22 | }
23 |
24 | fun getAudienceResult(): ArrayList {
25 | return audienceList
26 | }
27 |
28 | fun getError(): String? {
29 | return error
30 | }
31 |
32 | private fun parseJsonObject(jsonObject: JSONObject) {
33 | try {
34 | val audienceMemberships = jsonObject.getJSONArray("audience_memberships")
35 | for (i in 0 until audienceMemberships.length()) {
36 | val audience = audienceMemberships[i] as JSONObject
37 | val audienceID = audience["audience_id"]
38 | audienceList.add(Audience(audienceID.toString()))
39 | }
40 | } catch (e: Exception) {
41 | Logger.error("Exception while parsing audience response $e")
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/audience/AudienceTask.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.audience
2 |
3 |
4 | abstract class AudienceTask {
5 |
6 | abstract fun isComplete(): Boolean
7 |
8 | abstract fun isSuccessful(): Boolean
9 |
10 | abstract fun getResult(): AudienceTaskResult?
11 |
12 | abstract fun addSuccessListener(listener: AudienceTaskSuccessListener): AudienceTask
13 |
14 | abstract fun addFailureListener(listener: AudienceTaskFailureListener): AudienceTask
15 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/audience/AudienceTaskFailureListener.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.audience
2 |
3 | fun interface AudienceTaskFailureListener {
4 | fun onFailure(result: AudienceResponse?)
5 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/audience/AudienceTaskSuccessListener.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.audience
2 |
3 | fun interface AudienceTaskSuccessListener {
4 | fun onSuccess(result: AudienceResponse)
5 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/identity/UserAttributeListenerWrapper.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.identity
2 |
3 | import com.mparticle.TypedUserAttributeListener
4 | import com.mparticle.UserAttributeListener
5 | import com.mparticle.UserAttributeListenerType
6 |
7 | class UserAttributeListenerWrapper(val listener: UserAttributeListenerType) {
8 | fun onUserAttributesReceived(
9 | singles: Map?,
10 | lists: Map?>?,
11 | mpid: Long?
12 | ) {
13 | when (listener) {
14 | is UserAttributeListener -> (singles ?: mutableMapOf())
15 | .entries
16 | .associate { it.key to it.value?.toString() }
17 | .let { listener.onUserAttributesReceived(it, lists, mpid) }
18 | is TypedUserAttributeListener -> mpid?.let {
19 | listener.onUserAttributesReceived(
20 | singles ?: mutableMapOf(), lists ?: mutableMapOf(), it
21 | )
22 | }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/BatchId.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import com.mparticle.internal.database.services.MessageService.ReadyMessage
4 |
5 | class BatchId {
6 | val mpid: Long
7 | val sessionId: String?
8 | val dataplanId: String?
9 | val dataplanVersion: Int?
10 |
11 | constructor(mpid: Long, sessionId: String?, dataplanId: String?, dataplanVersion: Int?) {
12 | this.mpid = mpid
13 | this.sessionId = sessionId
14 | this.dataplanId = dataplanId
15 | this.dataplanVersion = dataplanVersion
16 | }
17 |
18 | constructor(readyMessage: ReadyMessage) {
19 | mpid = readyMessage.mpid
20 | sessionId = readyMessage.sessionId
21 | dataplanId = readyMessage.dataplanId
22 | dataplanVersion = readyMessage.dataplanVersion
23 | }
24 |
25 | override fun equals(obj: Any?): Boolean {
26 | if (obj !is BatchId) {
27 | return false
28 | }
29 | for (i in 0 until fields().size) {
30 | if (!MPUtility.isEqual(fields()[i], obj.fields()[i])) {
31 | return false
32 | }
33 | }
34 | return true
35 | }
36 |
37 | override fun hashCode(): Int {
38 | return fields().contentHashCode()
39 | }
40 |
41 | private fun fields(): Array {
42 | return arrayOf(mpid, sessionId, dataplanId, dataplanVersion)
43 | }
44 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/CoreCallbacks.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import android.app.Activity
4 | import android.net.Uri
5 | import androidx.annotation.WorkerThread
6 | import com.mparticle.MParticleOptions.DataplanOptions
7 | import org.json.JSONArray
8 | import java.lang.ref.WeakReference
9 |
10 | interface CoreCallbacks {
11 | fun isBackgrounded(): Boolean
12 |
13 | fun getUserBucket(): Int
14 |
15 | fun isEnabled(): Boolean
16 |
17 | fun setIntegrationAttributes(kitId: Int, integrationAttributes: Map)
18 |
19 | fun getIntegrationAttributes(kitId: Int): Map?
20 |
21 | fun getCurrentActivity(): WeakReference?
22 |
23 | @WorkerThread
24 | fun getLatestKitConfiguration(): JSONArray?
25 |
26 | fun getDataplanOptions(): DataplanOptions?
27 |
28 | fun isPushEnabled(): Boolean
29 |
30 | fun getPushSenderId(): String?
31 |
32 | fun getPushInstanceId(): String?
33 |
34 | fun getLaunchUri(): Uri?
35 |
36 | fun getLaunchAction(): String?
37 |
38 | fun getKitListener(): KitListener?
39 |
40 | interface KitListener {
41 | fun kitFound(kitId: Int)
42 |
43 | fun kitConfigReceived(kitId: Int, configuration: String?)
44 |
45 | fun kitExcluded(kitId: Int, reason: String?)
46 |
47 | fun kitStarted(kitId: Int)
48 | fun onKitApiCalled(kitId: Int, used: Boolean?, vararg objects: Any?)
49 | fun onKitApiCalled(methodName: String?, kitId: Int, used: Boolean?, vararg objects: Any?)
50 |
51 | companion object {
52 | @JvmField
53 | val EMPTY: KitListener = object : KitListener {
54 | override fun kitFound(kitId: Int) {}
55 | override fun kitConfigReceived(kitId: Int, configuration: String?) {}
56 | override fun kitExcluded(kitId: Int, reason: String?) {}
57 | override fun kitStarted(kitId: Int) {}
58 | override fun onKitApiCalled(kitId: Int, used: Boolean?, vararg objects: Any?) {}
59 | override fun onKitApiCalled(methodName: String?, kitId: Int, used: Boolean?, vararg objects: Any?) {}
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/JellybeanHelper.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import android.annotation.TargetApi
4 | import android.os.Build
5 | import android.os.StatFs
6 |
7 | /**
8 | * This is solely used to avoid logcat warnings that Android will generate when loading a class,
9 | * even if you use conditional execution based on VERSION.
10 | */
11 | @TargetApi(18)
12 | object JellybeanHelper {
13 | @JvmStatic
14 | fun getAvailableMemory(stat: StatFs): Long {
15 | try {
16 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
17 | return stat.availableBlocksLong * stat.blockSizeLong
18 | }
19 | } catch (e: Exception) {
20 | //For some reason, it appears some devices even in jelly bean don't have this method.
21 | }
22 |
23 | return 0
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/KitKatHelper.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import android.annotation.TargetApi
4 | import android.os.Build
5 | import org.json.JSONArray
6 |
7 | /**
8 | * This is solely used to avoid logcat warnings that Android will generate when loading a class,
9 | * even if you use conditional execution based on VERSION.
10 | */
11 | @TargetApi(19)
12 | object KitKatHelper {
13 | @JvmStatic
14 | fun remove(array: JSONArray, index: Int) {
15 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
16 | array.remove(index)
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/MPLifecycleCallbackDelegate.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import android.annotation.TargetApi
4 | import android.app.Activity
5 | import android.app.Application.ActivityLifecycleCallbacks
6 | import android.os.Build
7 | import android.os.Bundle
8 |
9 | /**
10 | * This class is used by the AppStateManager to determine when the app is visible or in the background.
11 | *
12 | * Separated into its own class to avoid annoying logcat messages on pre-ICS devices.
13 | */
14 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
15 | internal class MPLifecycleCallbackDelegate(private val mStateManager: AppStateManager) :
16 | ActivityLifecycleCallbacks {
17 | override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
18 | mStateManager.onActivityCreated(activity, savedInstanceState)
19 | }
20 |
21 | override fun onActivityStarted(activity: Activity) {
22 | mStateManager.onActivityStarted(activity)
23 | }
24 |
25 | override fun onActivityResumed(activity: Activity) {
26 | mStateManager.onActivityResumed(activity)
27 | }
28 |
29 | override fun onActivityPaused(activity: Activity) {
30 | mStateManager.onActivityPaused(activity)
31 | }
32 |
33 | override fun onActivityStopped(activity: Activity) {
34 | mStateManager.onActivityStopped(activity)
35 | }
36 |
37 | override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
38 | mStateManager.onActivitySaveInstanceState(activity, outState)
39 | }
40 |
41 | override fun onActivityDestroyed(activity: Activity) {
42 | mStateManager.onActivityDestroyed(activity)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/MPLocationListener.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import android.location.Location
4 | import android.location.LocationListener
5 | import android.os.Bundle
6 | import com.mparticle.MParticle
7 |
8 | class MPLocationListener(private val mParticle: MParticle) : LocationListener {
9 | override fun onLocationChanged(location: Location) {
10 | mParticle.setLocation(location)
11 | }
12 |
13 | override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
14 | }
15 |
16 | override fun onProviderEnabled(provider: String) {
17 | }
18 |
19 | override fun onProviderDisabled(provider: String) {
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/SideloadedKit.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import org.json.JSONObject
4 |
5 | interface SideloadedKit {
6 |
7 | fun getJsonConfig(): JSONObject?
8 |
9 | fun kitId(): Int
10 |
11 | fun getName(): String
12 | }
13 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/listeners/ApiClass.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.listeners
2 |
3 | @Retention(AnnotationRetention.BINARY)
4 | @Target(AnnotationTarget.CLASS)
5 | annotation class ApiClass
6 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/internal/listeners/GraphListener.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal.listeners
2 |
3 | import android.os.Message
4 |
5 | interface GraphListener {
6 | fun onCompositeObjects(child: Any?, parent: Any?)
7 |
8 | fun onThreadMessage(
9 | handlerName: String,
10 | msg: Message?,
11 | onNewThread: Boolean,
12 | stackTrace: Array?
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/rokt/RoktEmbeddedView.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.rokt
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.widget.FrameLayout
6 |
7 | class RoktEmbeddedView : FrameLayout {
8 | var dimensionCallBack: RoktLayoutDimensionCallBack? = null
9 |
10 | constructor(context: Context) : super(context)
11 |
12 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
13 |
14 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
15 | }
--------------------------------------------------------------------------------
/android-core/src/main/kotlin/com/mparticle/rokt/RoktLayoutDimensionCallBack.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.rokt
2 |
3 | interface RoktLayoutDimensionCallBack {
4 | fun onHeightChanged(height: Int)
5 | fun onMarginChanged(start: Int, top: Int, end: Int, bottom: Int)
6 | }
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/BaseEventTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | import org.junit.Assert
4 | import org.junit.Test
5 |
6 | class BaseEventTest {
7 | @Test
8 | fun testEventType() {
9 | val baseEvent = BaseEvent(BaseEvent.Type.COMMERCE_EVENT)
10 | Assert.assertEquals(BaseEvent.Type.COMMERCE_EVENT, baseEvent.type)
11 | }
12 |
13 | @Test
14 | fun testCustomFlags() {
15 | val baseEvent = BaseEvent(BaseEvent.Type.BREADCRUMB)
16 | Assert.assertNull(baseEvent.customFlags)
17 | val values1: MutableList = ArrayList()
18 | values1.add("val1")
19 | values1.add("val2")
20 | values1.add("val3")
21 | val values2: MutableList = ArrayList()
22 | values2.add("val2")
23 | val customFlags = HashMap>()
24 | customFlags["key1"] = values1
25 | customFlags["key2"] = values2
26 | customFlags["key3"] = ArrayList()
27 | baseEvent.customFlags = customFlags
28 |
29 | // should not be able to add null key
30 | customFlags[null] = ArrayList()
31 | baseEvent.customFlags = customFlags
32 | Assert.assertEquals(3, baseEvent.customFlags?.size)
33 | baseEvent.customFlags = null
34 | Assert.assertNull(baseEvent.customFlags)
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/MockMParticle.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | import com.mparticle.identity.IdentityApi
4 | import com.mparticle.internal.AppStateManager
5 | import com.mparticle.internal.ConfigManager
6 | import com.mparticle.internal.KitFrameworkWrapper
7 | import com.mparticle.internal.KitsLoadedCallback
8 | import com.mparticle.internal.MessageManager
9 | import com.mparticle.media.MPMediaAPI
10 | import com.mparticle.messaging.MPMessagingAPI
11 | import com.mparticle.mock.MockContext
12 | import org.mockito.Mockito
13 |
14 | class MockMParticle : MParticle() {
15 | init {
16 | mConfigManager = Mockito.mock(ConfigManager::class.java)
17 | mKitManager = Mockito.mock(KitFrameworkWrapper::class.java)
18 | mAppStateManager = Mockito.mock(AppStateManager::class.java)
19 | mConfigManager = Mockito.mock(ConfigManager::class.java)
20 | mKitManager = Mockito.mock(KitFrameworkWrapper::class.java)
21 | mMessageManager = Mockito.mock(MessageManager::class.java)
22 | mMessaging = Mockito.mock(MPMessagingAPI::class.java)
23 | mMedia = Mockito.mock(MPMediaAPI::class.java)
24 | mIdentityApi = IdentityApi(
25 | MockContext(),
26 | mAppStateManager,
27 | mMessageManager,
28 | mInternal.configManager,
29 | mKitManager,
30 | OperatingSystem.ANDROID
31 | )
32 | Mockito.`when`(mKitManager.updateKits(Mockito.any())).thenReturn(KitsLoadedCallback())
33 | val event = MPEvent.Builder("this")
34 | .customAttributes(HashMap())
35 | .build()
36 | val attributes = event.customAttributes
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/SessionTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | import org.junit.Assert
4 | import org.junit.Test
5 |
6 | class SessionTest {
7 |
8 | @Test
9 | fun equals() {
10 | var sessionA = Session(null, null)
11 | var sessionB = Session(null, null)
12 | Assert.assertEquals(sessionA, sessionB)
13 | val sessionC = Session(null, 123L)
14 | Assert.assertEquals(sessionA, sessionB)
15 | Assert.assertFalse(sessionA == sessionC)
16 | Assert.assertFalse(sessionC == sessionA)
17 | var sessionF = Session("foo", 123L)
18 | val sessionG = Session("foo", 456L)
19 | Assert.assertFalse(sessionF == sessionG)
20 | sessionF = Session("foo", null)
21 | Assert.assertFalse(sessionF == sessionG)
22 | sessionA = Session("foo", 456L)
23 | sessionB = Session("fOo", 456L)
24 | Assert.assertEquals(sessionA, sessionB)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/commerce/ProductTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.commerce
2 |
3 | import com.mparticle.MParticle
4 | import com.mparticle.MockMParticle
5 | import org.junit.Assert
6 | import org.junit.Before
7 | import org.junit.Test
8 |
9 | class ProductTest {
10 | @Before
11 | fun before() {
12 | MParticle.setInstance(MockMParticle())
13 | }
14 |
15 | @Test
16 | fun testDefaultEqualityComparator() {
17 | Product.setEqualityComparator(null)
18 | val product1 = Product.Builder("name", "sku", 2.0).brand("cool brand!").build()
19 | val product2 =
20 | Product.Builder("cool brand!", "sku", 2.0).brand("cool brand!adsflkjh").build()
21 | val product2Copy = Product.Builder(product2).build()
22 | product2Copy.mTimeAdded = product2.mTimeAdded
23 | Assert.assertNotEquals(product2, product1)
24 | Assert.assertEquals(product1, product1)
25 | Assert.assertEquals(product2, product2Copy)
26 | Assert.assertNotEquals(product1, null)
27 | Assert.assertNotEquals(null, product1)
28 | }
29 |
30 | @Test
31 | fun testEqualityComparator() {
32 | Product.setEqualityComparator { product1, product2 -> product1?.name == product2?.brand }
33 | val product1 = Product.Builder("name", "sku", 2.0).brand("cool brand!").build()
34 | val product2 =
35 | Product.Builder("cool brand!", "sku", 2.0).brand("cool brand!adsflkjh").build()
36 | Assert.assertEquals(product2, product1)
37 | }
38 |
39 | @Test
40 | fun testSerializationDeserialization() {
41 | Product.setEqualityComparator { product1, product2 -> product1.toString() == product2.toString() }
42 | val product = Product.Builder("product name", "product sku", 301.45)
43 | .brand("product brand")
44 | .category("product category")
45 | .couponCode("product coupon code")
46 | .name("product name")
47 | .position(4)
48 | .variant("product variant")
49 | .quantity(12.1)
50 | .build()
51 | val productJson = product.toJson()
52 | val product2 = Product.fromJson(productJson)
53 | Assert.assertEquals(product, product2)
54 | product2?.quantity = 10000.0
55 | Assert.assertNotEquals(product, product2)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/external/ApiVisibilityTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.external
2 |
3 | import com.mparticle.MParticle
4 | import com.mparticle.Session
5 | import org.junit.Assert
6 | import org.junit.Test
7 | import java.lang.reflect.Modifier
8 |
9 | class ApiVisibilityTest {
10 | @Test
11 | @Throws(Exception::class)
12 | fun testMParticleApiVisibility() {
13 | val mpMethods = MParticle::class.java.declaredMethods
14 | var publicMethodCount = 0
15 | for (m in mpMethods) {
16 | if (Modifier.isPublic(m.modifiers)) {
17 | publicMethodCount++
18 | }
19 | }
20 | Assert.assertEquals(66, publicMethodCount)
21 | }
22 |
23 | @Test
24 | @Throws(Exception::class)
25 | fun testSessionApiVisibility() {
26 | val mpMethods = Session::class.java.declaredMethods
27 | var publicMethodCount = 0
28 | for (m in mpMethods) {
29 | if (Modifier.isPublic(m.modifiers)) {
30 | publicMethodCount++
31 | }
32 | }
33 | Assert.assertEquals(4, publicMethodCount)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/identity/MParticleIdentityClientImplTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.identity
2 |
3 | import android.content.Context
4 | import com.mparticle.MParticle
5 | import com.mparticle.MParticle.IdentityType
6 | import com.mparticle.internal.ConfigManager
7 | import org.junit.Assert
8 | import org.junit.Test
9 | import org.mockito.Mockito
10 |
11 | class MParticleIdentityClientImplTest {
12 | @Test
13 | @Throws(Exception::class)
14 | fun testConvertIdentityTypeToString() {
15 | for (type in IdentityType.values()) {
16 | Assert.assertEquals(
17 | type,
18 | MParticleIdentityClientImpl.getIdentityType(
19 | MParticleIdentityClientImpl.getStringValue(type)
20 | )
21 | )
22 | }
23 | }
24 |
25 | @Test
26 | fun testOperatingSystemToString() {
27 | // make sure that all the cases are covered, default is not getting returned
28 | // if this test fails, it might be because you added a new OperatingSystem enum, but forgot
29 | // to update this method
30 | val osStringValues = HashSet()
31 | for (operatingSystem in MParticle.OperatingSystem.values()) {
32 | val osString = MParticleIdentityClientImpl(
33 | Mockito.mock(
34 | Context::class.java
35 | ),
36 | Mockito.mock(
37 | ConfigManager::class.java
38 | ),
39 | operatingSystem
40 | ).operatingSystemString
41 | Assert.assertFalse(osStringValues.contains(osString))
42 | osStringValues.add(osString)
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/internal/InstallReceiverHelperTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import android.content.Context
4 | import com.mparticle.InstallReferrerHelper
5 | import com.mparticle.mock.MockContext
6 | import org.junit.Test
7 |
8 | class InstallReceiverHelperTest {
9 | @Test
10 | @Throws(Exception::class)
11 | fun testNullInputs() {
12 | val context: Context = MockContext()
13 | InstallReferrerHelper.setInstallReferrer(context, "")
14 | InstallReferrerHelper.setInstallReferrer(context, null)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/internal/InternalSessionTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.internal
2 |
3 | import com.mparticle.mock.MockContext
4 | import org.junit.Assert
5 | import org.junit.Test
6 |
7 | class InternalSessionTest {
8 | @Test
9 | fun testSessionIdsAreCapitalized() {
10 | val session = InternalSession()
11 | session.start(MockContext())
12 | val sessionId = session.mSessionID
13 | Assert.assertNotEquals(Constants.NO_SESSION_ID, sessionId)
14 | Assert.assertEquals(sessionId.uppercase(), sessionId)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/networking/CertificateTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking
2 |
3 | import com.mparticle.testutils.RandomUtils
4 | import org.junit.Assert.assertEquals
5 | import org.junit.Assert.assertNull
6 | import org.junit.Test
7 |
8 | class CertificateTest {
9 | val randomUtils = RandomUtils()
10 | val alias = randomUtils.getAlphaNumericString(10)
11 | val certificateString = randomUtils.getAlphaNumericString(124)
12 |
13 | @Test
14 | fun buildCertificateTest() {
15 | val certificate = Certificate.with(alias, certificateString)
16 | assertEquals(alias, certificate?.getAlias())
17 | assertEquals(certificateString, certificate?.getCertificate())
18 | }
19 |
20 | @Test
21 | fun rejectMalformedCertificate() {
22 | var certificate = Certificate.with("", certificateString)
23 | assertNull(certificate)
24 |
25 | certificate = Certificate.with(alias, "")
26 | assertNull(certificate)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/android-core/src/test/kotlin/com/mparticle/networking/EndpointTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking
2 |
3 | import org.junit.Assert
4 | import org.junit.Test
5 |
6 | class EndpointTest {
7 | @Test
8 | fun parseEnumTest() {
9 | for (endpoint in MParticleBaseClientImpl.Endpoint.values()) {
10 | Assert.assertEquals(endpoint, MParticleBaseClientImpl.Endpoint.parseInt(endpoint.value))
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android-kit-base/libs/java-json.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mParticle/mparticle-android-sdk/6243d3ce106adc537f7ac9dcff44d7746929e514/android-kit-base/libs/java-json.jar
--------------------------------------------------------------------------------
/android-kit-base/proguard.pro:
--------------------------------------------------------------------------------
1 |
2 | # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
3 | -keepclasseswithmembernames class * {
4 | native ;
5 | }
6 |
7 | -keepparameternames
8 | -renamesourcefileattribute SourceFile
9 | -keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
10 | -repackageclasses com.mparticle
11 |
12 | -keep class com.mparticle.kits.MPSideloadedKit { *; }
13 | -keep class com.mparticle.kits.MPSideloadedFilters { *; }
14 |
15 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/ConfiguredKitOptions.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import org.json.JSONObject
4 |
5 | class ConfiguredKitOptions : KitOptions() {
6 | val testingConfiguration = mutableMapOf()
7 |
8 | override fun addKit(kitId: Int, type: Class): ConfiguredKitOptions {
9 | return addKit(kitId, type, JSONObject().put("id", kitId))
10 | }
11 |
12 | fun addKit(
13 | kitId: Int,
14 | type: Class,
15 | config: JSONObject?
16 | ): ConfiguredKitOptions {
17 | testingConfiguration[kitId] = config?.put("id", kitId)
18 | super.addKit(kitId, type)
19 | return this
20 | }
21 | }
22 |
23 | fun ConfiguredKitOptions(configuredKitOptions: ConfiguredKitOptions.() -> Unit): ConfiguredKitOptions {
24 | return ConfiguredKitOptions().apply(configuredKitOptions)
25 | }
26 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/GCMPushMessageForwardingTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import android.content.Intent
4 | import android.net.Uri
5 | import android.os.Bundle
6 | import com.mparticle.MPServiceUtil
7 | import com.mparticle.MParticle
8 | import com.mparticle.MParticleOptions
9 | import com.mparticle.kits.testkits.PushListenerTestKit
10 | import org.junit.Assert.assertEquals
11 | import org.junit.Assert.assertNotNull
12 | import org.junit.Test
13 |
14 | class GCMPushMessageForwardingTest : BaseKitOptionsTest() {
15 |
16 | @Test
17 | fun testPushForwardedAfterSDKStarted() {
18 | var receivedIntent: Intent? = null
19 |
20 | MParticleOptions.builder(mContext)
21 | .credentials("key", "secret")
22 | .configuration(KitOptions().addKit(1, PushListenerTestKit::class.java))
23 | .let {
24 | startMParticle(it)
25 | }
26 |
27 | val intent = Intent()
28 | .apply {
29 | action = "com.google.android.c2dm.intent.RECEIVE"
30 | data = Uri.EMPTY
31 | putExtras(Bundle())
32 | }
33 | (MParticle.getInstance()?.getKitInstance(1) as PushListenerTestKit).onPushMessageReceived =
34 | { context, intent ->
35 | receivedIntent = intent
36 | }
37 | MPServiceUtil(mContext).onHandleIntent(intent)
38 |
39 | assertNotNull(receivedIntent)
40 | assertEquals(intent, receivedIntent)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/KitManagerImplTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import org.junit.Assert
4 | import org.junit.Test
5 |
6 | class KitManagerImplTest {
7 | @Test
8 | fun tokenTest() {
9 | Assert.assertTrue(true)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/KnownUserKitsLifecycleTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import android.content.Context
4 | import com.mparticle.MParticleOptions
5 | import com.mparticle.kits.testkits.ListenerTestKit
6 | import org.json.JSONException
7 | import org.json.JSONObject
8 | import org.junit.Before
9 |
10 | class KnownUserKitsLifecycleTest : BaseKitOptionsTest() {
11 | @Before
12 | @Throws(JSONException::class)
13 | fun before() {
14 | val builder = MParticleOptions.builder(mContext)
15 | .configuration(
16 | ConfiguredKitOptions()
17 | .addKit(-1, TestKit1::class.java, JSONObject().put("eau", true))
18 | .addKit(-2, TestKit2::class.java, JSONObject().put("eau", false))
19 | .addKit(-3, TestKit3::class.java, JSONObject().put("eau", true))
20 | )
21 | startMParticle(builder)
22 | }
23 |
24 | class TestKit1 : TestKit()
25 | class TestKit2 : TestKit()
26 | class TestKit3 : TestKit()
27 | open class TestKit : ListenerTestKit() {
28 | override fun getName(): String {
29 | return "test kit" + i++
30 | }
31 |
32 | @Throws(IllegalArgumentException::class)
33 | override fun onKitCreate(
34 | settings: Map?,
35 | context: Context
36 | ): List {
37 | return emptyList()
38 | }
39 |
40 | override fun setOptOut(optedOut: Boolean): List {
41 | return emptyList()
42 | }
43 |
44 | companion object {
45 | var i = 0
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/testkits/BaseTestKit.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits.testkits
2 |
3 | import android.content.Context
4 | import com.mparticle.kits.KitIntegration
5 | import com.mparticle.kits.ReportingMessage
6 |
7 | open class BaseTestKit : KitIntegration() {
8 | open override fun onKitCreate(
9 | settings: Map?,
10 | context: Context
11 | ): List {
12 | return listOf()
13 | }
14 |
15 | open override fun setOptOut(optedOut: Boolean): List {
16 | // do nothing
17 | return listOf()
18 | }
19 |
20 | open override fun getName(): String {
21 | return this::class.java.simpleName
22 | }
23 |
24 | open override fun getInstance() = this
25 | }
26 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/testkits/CommerceListenerTestKit.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits.testkits
2 |
3 | import com.mparticle.commerce.CommerceEvent
4 | import com.mparticle.kits.KitIntegration
5 | import com.mparticle.kits.ReportingMessage
6 | import java.math.BigDecimal
7 |
8 | class CommerceListenerTestKit : ListenerTestKit(), KitIntegration.CommerceListener {
9 | var logEvent: ((CommerceEvent?) -> List)? = null
10 | var logLtvIncrease: ((BigDecimal?, BigDecimal?, String?, Map?) -> List)? =
11 | null
12 |
13 | override fun logEvent(event: CommerceEvent?): List {
14 | return logEvent?.invoke(event) ?: listOf()
15 | }
16 |
17 | override fun logLtvIncrease(
18 | valueIncreased: BigDecimal?,
19 | valueTotal: BigDecimal?,
20 | eventName: String?,
21 | contextInfo: Map?
22 | ): List {
23 | return logLtvIncrease?.invoke(valueIncreased, valueTotal, eventName, contextInfo)
24 | ?: listOf()
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/testkits/EventTestKit.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits.testkits
2 |
3 | import com.mparticle.MPEvent
4 | import com.mparticle.kits.KitIntegration
5 | import com.mparticle.kits.ReportingMessage
6 |
7 | class EventTestKit : ListenerTestKit(), KitIntegration.EventListener {
8 | var onLogEvent: (MPEvent) -> MutableList? = { null }
9 |
10 | override fun logEvent(baseEvent: MPEvent): MutableList? {
11 | return onLogEvent(baseEvent)
12 | }
13 |
14 | override fun leaveBreadcrumb(breadcrumb: String?): MutableList {
15 | TODO("Not yet implemented")
16 | }
17 |
18 | override fun logError(
19 | message: String?,
20 | errorAttributes: MutableMap?
21 | ): MutableList {
22 | TODO("Not yet implemented")
23 | }
24 |
25 | override fun logException(
26 | exception: Exception?,
27 | exceptionAttributes: MutableMap?,
28 | message: String?
29 | ): MutableList {
30 | TODO("Not yet implemented")
31 | }
32 |
33 | override fun logScreen(
34 | screenName: String?,
35 | screenAttributes: MutableMap?
36 | ): MutableList {
37 | TODO("Not yet implemented")
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/testkits/IdentityListenerTestKit.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits.testkits
2 |
3 | import com.mparticle.identity.MParticleUser
4 | import com.mparticle.kits.FilteredIdentityApiRequest
5 | import com.mparticle.kits.KitIntegration
6 |
7 | open class IdentityListenerTestKit : ListenerTestKit(), KitIntegration.IdentityListener {
8 | var onIdentifyCompleted: ((mParticleUser: MParticleUser?, identityApiRequest: FilteredIdentityApiRequest?) -> Unit)? =
9 | null
10 | var onLoginCompleted: ((mParticleUser: MParticleUser?, identityApiRequest: FilteredIdentityApiRequest?) -> Unit)? =
11 | null
12 | var onLogoutCompleted: ((mParticleUser: MParticleUser?, identityApiRequest: FilteredIdentityApiRequest?) -> Unit)? =
13 | null
14 | var onModifyCompleted: ((mParticleUser: MParticleUser?, identityApiRequest: FilteredIdentityApiRequest?) -> Unit)? =
15 | null
16 | var onUserIdentified: ((mParticleUser: MParticleUser?) -> Unit)? = null
17 |
18 | override fun onLogoutCompleted(
19 | mParticleUser: MParticleUser?,
20 | identityApiRequest: FilteredIdentityApiRequest?
21 | ) {
22 | onLogoutCompleted?.invoke(mParticleUser, identityApiRequest)
23 | onUserReceived?.invoke(mParticleUser)
24 | }
25 |
26 | override fun onLoginCompleted(
27 | mParticleUser: MParticleUser?,
28 | identityApiRequest: FilteredIdentityApiRequest?
29 | ) {
30 | onLoginCompleted?.invoke(mParticleUser, identityApiRequest)
31 | onUserReceived?.invoke(mParticleUser)
32 | }
33 |
34 | override fun onIdentifyCompleted(
35 | mParticleUser: MParticleUser?,
36 | identityApiRequest: FilteredIdentityApiRequest?
37 | ) {
38 | onIdentifyCompleted?.invoke(mParticleUser, identityApiRequest)
39 | onUserReceived?.invoke(mParticleUser)
40 | }
41 |
42 | override fun onModifyCompleted(
43 | mParticleUser: MParticleUser?,
44 | identityApiRequest: FilteredIdentityApiRequest?
45 | ) {
46 | onModifyCompleted?.invoke(mParticleUser, identityApiRequest)
47 | onUserReceived?.invoke(mParticleUser)
48 | }
49 |
50 | override fun onUserIdentified(mParticleUser: MParticleUser?) {
51 | onUserIdentified?.invoke(mParticleUser)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/testkits/ListenerTestKit.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits.testkits
2 |
3 | import android.content.Context
4 | import com.mparticle.MParticle
5 | import com.mparticle.identity.MParticleUser
6 | import com.mparticle.kits.ReportingMessage
7 |
8 | abstract class ListenerTestKit : BaseTestKit() {
9 | var onUserReceived: ((MParticleUser?) -> Unit)? = null
10 | var onIdentityReceived: ((MParticle.IdentityType, String?) -> Unit)? = null
11 | var onAttributeReceived: ((String?, Any?) -> Unit)? = null
12 |
13 | var onKitCreate: ((settings: Map?, context: Context) -> List)? =
14 | null
15 | var setOptOut: ((optedOut: Boolean) -> List)? = null
16 | var getName: (() -> String)? = null
17 |
18 | override fun getName() = getName?.invoke() ?: "Test Kit thing"
19 | override fun setOptOut(optedOut: Boolean) = setOptOut?.invoke(optedOut)
20 | ?: listOf()
21 |
22 | override fun onKitCreate(
23 | settings: Map?,
24 | context: Context
25 | ): List = onKitCreate?.invoke(settings, context)
26 | ?: listOf()
27 | }
28 |
--------------------------------------------------------------------------------
/android-kit-base/src/androidTest/kotlin/com/mparticle/kits/testkits/PushListenerTestKit.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits.testkits
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import com.mparticle.kits.KitIntegration
6 |
7 | class PushListenerTestKit : BaseTestKit(), KitIntegration.PushListener {
8 | var onPushMessageReceived: (Context, Intent?) -> Unit = { _, _ -> }
9 | var onPushRegistration: (String?, String?) -> Boolean = { _, _ -> false }
10 | override fun willHandlePushMessage(intent: Intent?) = true
11 |
12 | override fun onPushMessageReceived(context: Context, pushIntent: Intent?) {
13 | onPushMessageReceived.invoke(context, pushIntent)
14 | }
15 |
16 | override fun onPushRegistration(instanceId: String?, senderId: String?): Boolean {
17 | return onPushRegistration.invoke(instanceId, senderId)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/android-kit-base/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/android-kit-base/src/main/java/com/mparticle/kits/FilteredIdentityApiRequest.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits;
2 |
3 | import com.mparticle.MParticle;
4 | import com.mparticle.identity.IdentityApiRequest;
5 |
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | public class FilteredIdentityApiRequest {
10 | KitIntegration provider;
11 | Map userIdentities = new HashMap<>();
12 |
13 | FilteredIdentityApiRequest(IdentityApiRequest identityApiRequest, KitIntegration provider) {
14 | if (identityApiRequest != null) {
15 | userIdentities = new HashMap<>(identityApiRequest.getUserIdentities());
16 | if (provider.getKitManager() != null) {
17 | userIdentities = provider.getKitManager().getDataplanFilter().transformIdentities(userIdentities);
18 | }
19 | }
20 | this.provider = provider;
21 | }
22 |
23 | @Deprecated
24 | public Map getNewIdentities() {
25 | return getUserIdentities();
26 | }
27 |
28 | public Map getUserIdentities() {
29 | Map identities = userIdentities;
30 | Map filteredIdentities = new HashMap(identities.size());
31 | for (Map.Entry entry : identities.entrySet()) {
32 | if (provider.getConfiguration().shouldSetIdentity(entry.getKey())) {
33 | filteredIdentities.put(entry.getKey(), entry.getValue());
34 | }
35 | }
36 | return filteredIdentities;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/android-kit-base/src/main/java/com/mparticle/kits/MPSideloadedFilters.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import org.json.JSONObject
4 |
5 | class MPSideloadedFilters {
6 |
7 | var filters: MutableMap = mutableMapOf()
8 | private set
9 | }
10 |
--------------------------------------------------------------------------------
/android-kit-base/src/main/java/com/mparticle/kits/MPSideloadedKit.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import android.content.Context
4 | import com.mparticle.internal.SideloadedKit
5 | import org.json.JSONObject
6 |
7 | abstract class MPSideloadedKit(val kitId: Int) : KitIntegration(), SideloadedKit {
8 |
9 | companion object {
10 | const val MIN_SIDELOADED_KIT = 1000000
11 | }
12 |
13 | init {
14 | configuration = KitConfiguration.createKitConfiguration(
15 | JSONObject().put(
16 | KitConfiguration.KEY_ID,
17 | kitId
18 | )
19 | )
20 | }
21 |
22 | override fun kitId(): Int = kitId
23 |
24 | override fun getName(): String = this::class.java.name.split(".").last().orEmpty()
25 |
26 | override fun onKitCreate(
27 | settings: MutableMap?,
28 | context: Context?
29 | ): MutableList = mutableListOf()
30 |
31 | override fun setOptOut(optedOut: Boolean): MutableList = mutableListOf()
32 |
33 | fun addFilters(filter: MPSideloadedFilters): MPSideloadedKit {
34 | configuration = configuration.applyFilters(filter)
35 | return this
36 | }
37 |
38 | override fun getJsonConfig(): JSONObject? = super.getJsonConfig()
39 |
40 | private fun KitConfiguration.applyFilters(filters: MPSideloadedFilters): KitConfiguration? {
41 | return configuration?.applySideloadedKits(filters)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/android-kit-base/src/main/kotlin/com/mparticle/kits/KitOptions.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import com.mparticle.Configuration
4 |
5 | open class KitOptions(initializer: KitOptions.() -> Unit = {}) : Configuration {
6 | val kits: MutableMap> = mutableMapOf()
7 |
8 | init {
9 | this.initializer()
10 | }
11 |
12 | open fun addKit(kitId: Int, type: Class): KitOptions {
13 | kits[kitId] = type
14 | return this
15 | }
16 |
17 | override fun configures(): Class {
18 | return KitManagerImpl::class.java
19 | }
20 |
21 | override fun apply(kitManager: KitManagerImpl) {
22 | kitManager.setKitOptions(this)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/android-kit-base/src/test/kotlin/com/mparticle/kits/CommerceEventUtilsTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import org.junit.Assert
4 | import org.junit.Test
5 |
6 | class CommerceEventUtilsTest {
7 | @Test
8 | @Throws(Exception::class)
9 | fun testNullProductExpansion() {
10 | Assert.assertNotNull(CommerceEventUtils.expand(null))
11 | Assert.assertEquals(0, CommerceEventUtils.expand(null).size.toLong())
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android-kit-base/src/test/kotlin/com/mparticle/kits/KitUtilsTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import org.junit.Assert
4 | import org.junit.Test
5 | import java.util.LinkedList
6 |
7 | class KitUtilsTest {
8 | @Test
9 | @Throws(Exception::class)
10 | fun testSanitizeAttributeKey() {
11 | Assert.assertNull(KitUtils.sanitizeAttributeKey(null))
12 | Assert.assertEquals("", KitUtils.sanitizeAttributeKey(""))
13 | Assert.assertEquals("TestTest", KitUtils.sanitizeAttributeKey("\$TestTest"))
14 | Assert.assertEquals("$", KitUtils.sanitizeAttributeKey("$$"))
15 | Assert.assertEquals("", KitUtils.sanitizeAttributeKey("$"))
16 | }
17 |
18 | @Test
19 | @Throws(Exception::class)
20 | fun testJoin() {
21 | val testList: MutableList = LinkedList()
22 | testList.add("1")
23 | testList.add("test")
24 | testList.add("test 2")
25 | Assert.assertEquals("1,test,test 2", KitUtils.join(testList))
26 | Assert.assertEquals("", KitUtils.join(LinkedList()))
27 | val singleElementList: MutableList = LinkedList()
28 | singleElementList.add("tester")
29 | Assert.assertEquals("tester", KitUtils.join(singleElementList))
30 | }
31 |
32 | @Test
33 | @Throws(Exception::class)
34 | fun testJoinWithDelimiter() {
35 | val testList: MutableList = LinkedList()
36 | testList.add("1")
37 | testList.add("test")
38 | testList.add("test 2")
39 | Assert.assertEquals("", KitUtils.join(LinkedList(), "whatever"))
40 | val singleElementList: MutableList = LinkedList()
41 | singleElementList.add("tester")
42 | Assert.assertEquals("tester", KitUtils.join(singleElementList, "whatever"))
43 | Assert.assertEquals("1whatevertestwhatevertest 2", KitUtils.join(testList, "whatever"))
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.9.0'
3 | ext.gradle_version = '7.3.1'
4 |
5 | repositories {
6 | mavenCentral()
7 | google()
8 | }
9 | dependencies {
10 | classpath "com.android.tools.build:gradle:$gradle_version"
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 | }
13 | }
14 |
15 | plugins {
16 | id "org.sonarqube" version "3.5.0.2730"
17 | id "org.jlleitschuh.gradle.ktlint" version "11.2.0"
18 | }
19 |
20 | sonarqube {
21 | properties {
22 | property "sonar.projectKey", "mParticle_mparticle-android-sdk"
23 | property "sonar.organization", "mparticle"
24 | property "sonar.host.url", "https://sonarcloud.io"
25 | }
26 | }
27 |
28 | subprojects {
29 | apply plugin: 'org.sonarqube'
30 | sonarqube {
31 | androidVariant "release"
32 | }
33 | apply plugin: 'org.jlleitschuh.gradle.ktlint'
34 | }
35 |
36 | allprojects {
37 | group = 'com.mparticle'
38 | version = '5.65.0-SNAPSHOT'
39 | if (project.hasProperty('isRelease') && project.isRelease) {
40 | version = version.toString().replace("-SNAPSHOT", "")
41 | }
42 |
43 | repositories {
44 | mavenLocal()
45 | google()
46 | mavenCentral()
47 | }
48 |
49 | tasks.withType(Javadoc) {
50 | options.addStringOption('Xdoclint:none', '-quiet')
51 | }
52 |
53 | apply plugin: 'org.jlleitschuh.gradle.ktlint'
54 | }
55 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #android.enableJetifier=true
2 | android.useAndroidX=true
3 | org.gradle.daemon=true
4 | org.gradle.jvmargs=-Xmx2560m
5 | #-XX:ThreadStackSize=4096 -XX:CompilerThreadStackSize=4096
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mParticle/mparticle-android-sdk/6243d3ce106adc537f7ac9dcff44d7746929e514/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Oct 04 12:58:48 PDT 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/kit-plugin/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'groovy'
2 |
3 | ext {
4 | kitDescription = 'mParticle Gradle Plugin for creating mParticle kits'
5 | }
6 |
7 | apply from: '../scripts/maven.gradle'
8 |
9 | dependencies {
10 | implementation gradleApi()
11 | implementation localGroovy()
12 | compileOnly "com.android.tools.build:gradle:7.3.1"
13 | testImplementation "com.android.tools.build:gradle:4.1.3"
14 | }
15 |
16 | compileGroovy {
17 | sourceCompatibility = JavaVersion.VERSION_1_8
18 | targetCompatibility = JavaVersion.VERSION_1_8
19 | }
20 |
21 | dependencies {
22 | testImplementation 'junit:junit:4.13.2'
23 | }
24 |
25 | tasks.withType(Test) {
26 | jvmArgs('--add-opens=java.base/java.lang=ALL-UNNAMED')
27 | }
28 |
29 | task generateJavadocsJar(type: Jar, dependsOn: groovydoc) {
30 | archiveClassifier.set("javadoc")
31 | from groovydoc.destinationDir
32 | }
33 |
34 | task generateSourcesJar(type: Jar) {
35 | archiveClassifier.set("sources")
36 | from sourceSets.main.java.srcDirs
37 | }
38 |
--------------------------------------------------------------------------------
/kit-plugin/src/main/groovy/com/mparticle/kits/MParticlePluginExtension.groovy:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | /**
4 | * Created by sdozor on 4/25/16.
5 | */
6 | class MParticlePluginExtension {
7 | public String kitDescription
8 | }
9 |
--------------------------------------------------------------------------------
/kit-plugin/src/main/resources/META-INF/gradle-plugins/com.mparticle.kit.properties:
--------------------------------------------------------------------------------
1 | implementation-class=com.mparticle.kits.KitPlugin
2 |
--------------------------------------------------------------------------------
/kit-plugin/src/test/groovy/com/mparticle/kits/KitPluginTest.groovy:
--------------------------------------------------------------------------------
1 | package com.mparticle.kits
2 |
3 | import org.gradle.api.Project
4 | import org.gradle.testfixtures.ProjectBuilder
5 | import org.junit.Test
6 |
7 | class KitPluginTest {
8 | @Test
9 | void greeterPluginAddsGreetingTaskToProject() {
10 | Project project = ProjectBuilder.builder().build()
11 |
12 | project.pluginManager.apply 'com.mparticle.kit'
13 |
14 | project.mparticle.kitDescription = 'This is a sample kit description.'
15 |
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/kits/merge-updates.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | : "${2?"Kit Test Branch missing - usage: $0 \{branch_name\} \{target_branch\}"}"
3 |
4 | CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD`
5 | echo "Fetch"
6 | git fetch origin
7 | echo "Rebase"
8 | git rebase origin/"$1"
9 | echo "Push Updated Branch"
10 | git push origin "$2"
11 | echo "Delete Kit Feature branch Locally"
12 | git branch -D "$1"
13 | echo "Push Delete remote"
14 | git push origin --delete "$1"
15 | git checkout "$CURRENT_BRANCH"
16 |
--------------------------------------------------------------------------------
/scripts/kits/update.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | : "${1?"Kit Test Branch missing - usage: $0 \{branch_name\}"}"
3 |
4 | CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD`
5 | # checkout a kit branch for testing
6 | git branch -D "$1"
7 | git checkout -b "$1"
8 |
9 | # update kit references
10 | git submodule foreach "git fetch; git reset --hard origin/master";
11 |
12 | # commit kit reference deltas and push to private
13 | git add kits/*;
14 | git commit -m "Update submodules"
15 | git push -f origin "$1"
16 |
17 | git checkout "$CURRENT_BRANCH"
18 |
--------------------------------------------------------------------------------
/scripts/release.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | : ${1?"Version missing - usage: $0 x.y.z"} # nosemgrep
3 |
4 | #update build.gradle
5 | sed -i '.bak' "s/version = '.*-SNAPSHOT/version = '$1-SNAPSHOT/g" build.gradle
6 |
7 | #update README.md
8 | sed -i '.bak' "s/'com.mparticle:android-core:.*'/'com.mparticle:android-core:$1'/g" README.md
9 | sed -i '.bak' "s/'com.mparticle:android-example-kit:.*'/'com.mparticle:android-example-kit:$1'/g" README.md
10 | sed -i '.bak' "s/'com.mparticle:android-another-kit:.*'/'com.mparticle:android-another-kit:$1'/g" README.md
11 |
12 | #commit the version bump, tag, and push to private and public
13 | git add build.gradle
14 | git add README.md
15 |
--------------------------------------------------------------------------------
/scripts/startup_perf_tests.sh:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mParticle/mparticle-android-sdk/6243d3ce106adc537f7ac9dcff44d7746929e514/scripts/startup_perf_tests.sh
--------------------------------------------------------------------------------
/settings-kits.gradle:
--------------------------------------------------------------------------------
1 | //keep things alphabetical like readme
2 |
3 | include (
4 | ':kits:adjust-kit',
5 | ':kits:adobe-kit',
6 | ':kits:adobemedia-kit',
7 | ':kits:appboy-kit',
8 | ':kits:appsflyer-kit',
9 | ':kits:apptentive-kit',
10 | ':kits:apptimize-kit',
11 | ':kits:apteligent-kit',
12 | //blueshift hosts kit
13 | ':kits:branch-kit',
14 | ':kits:button-kit',
15 | ':kits:clevertap-kit',
16 | ':kits:comscore-kit',
17 | ':kits:flurry-kit',
18 | ':kits:foresee-kit',
19 | ':kits:googleanalyticsfirebase-kit',
20 | ':kits:googleanalyticsfirebasega4-kit',
21 | ':kits:iterable-kit',
22 | ':kits:kochava-kit',
23 | ':kits:leanplum-kit',
24 | ':kits:localytics-kit',
25 | //Neura hosts kit
26 | ':kits:onetrust-kit',
27 | ':kits:optimizely-kit',
28 | // ':kits:pilgrim-kit',
29 | ':kits:radar-kit',
30 | ':kits:responsys-kit',
31 | ':kits:revealmobile-kit',
32 | ':kits:rokt-kit',
33 | ':kits:singular-kit',
34 | ':kits:skyhook-kit',
35 | //Swrve hosts kit
36 | ':kits:taplytics-kit',
37 | ':kits:tune-kit',
38 | ':kits:urbanairship-kit',
39 | ':kits:wootric-kit',
40 | ':kits:example-kit'
41 | )
42 | project(':kits').getChildren().each {
43 | proj -> proj.name = 'android-' + proj.name
44 | }
45 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':android-core',
2 | ':testutils',
3 | ':android-kit-base',
4 | ':kit-plugin',
5 | ':tooling:custom-lint-rules',
6 | ':tooling:android-plugin',
7 | ':tooling:common'
8 |
9 |
10 | project(':kit-plugin').name = 'android-kit-plugin'
11 | project(':tooling:android-plugin').name = 'android-plugin'
--------------------------------------------------------------------------------
/testutils/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testutils/src/androidTest/java/com/mparticle/LegacyStartupTest.java:
--------------------------------------------------------------------------------
1 | package com.mparticle;
2 |
3 | import android.Manifest;
4 | import android.content.Context;
5 |
6 | import androidx.test.rule.GrantPermissionRule;
7 |
8 | import com.mparticle.internal.Logger;
9 |
10 | import org.junit.After;
11 | import org.junit.Assume;
12 | import org.junit.Before;
13 | import org.junit.Rule;
14 |
15 | import java.lang.reflect.Method;
16 |
17 | @LegacyOnly
18 | public class LegacyStartupTest extends BaseStartupTest {
19 |
20 | Method mParticleStart = null;
21 |
22 | @Rule
23 | public GrantPermissionRule mWritePermissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE);
24 |
25 | @Rule
26 | public GrantPermissionRule mReadPermissionRule = GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE);
27 |
28 |
29 | @Before
30 | public void before() throws InterruptedException {
31 | try {
32 | mParticleStart = MParticle.class.getMethod("start", Context.class, String.class, String.class);
33 | } catch (NoSuchMethodException e) {
34 | e.printStackTrace();
35 | }
36 | Assume.assumeNotNull(mParticleStart);
37 | }
38 |
39 | @After
40 | public void after() {
41 | try {
42 | Logger.debug("Startup times = " + readFile());
43 | } catch (Exception ex) {
44 | }
45 | }
46 |
47 | @Override
48 | protected String fileName() {
49 | return LEGACY_FILE_NAME;
50 | }
51 |
52 | @Override
53 | protected void startup() throws Exception {
54 | mParticleStart.invoke(null, mContext, "key", "secret");
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/testutils/src/androidTest/java/com/mparticle/MPUtilityVariantTest.java:
--------------------------------------------------------------------------------
1 | package com.mparticle;
2 |
3 | import static org.junit.Assert.assertTrue;
4 |
5 | import com.mparticle.internal.MPUtility;
6 |
7 | import org.junit.Test;
8 |
9 | public class MPUtilityVariantTest {
10 |
11 | @Test
12 | public void testFirebasePreset() {
13 | assertTrue(MPUtility.isFirebaseAvailable());
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/testutils/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/google/firebase/iid/FirebaseInstanceId.kt:
--------------------------------------------------------------------------------
1 | package com.google.firebase.iid
2 |
3 | object FirebaseInstanceIdToken {
4 | var token: String? = null
5 | }
6 |
7 | class FirebaseInstanceId {
8 |
9 | companion object {
10 | @JvmStatic
11 | fun getInstance() = FirebaseInstanceId()
12 |
13 | @JvmStatic
14 | fun setToken(token: String?) {
15 | FirebaseInstanceIdToken.token = token
16 | }
17 | }
18 |
19 | fun getToken() = FirebaseInstanceIdToken.token
20 | fun getToken(authority: String, scope: String) = FirebaseInstanceIdToken.token
21 | }
22 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/google/firebase/iid/FirebaseInstanceIdService.java:
--------------------------------------------------------------------------------
1 | package com.google.firebase.iid;
2 |
3 | import com.mparticle.testutils.TestingUtils;
4 |
5 | public class FirebaseInstanceIdService {
6 |
7 | static {
8 | if (!TestingUtils.isFirebasePresent()) {
9 | throw new RuntimeException(new ClassCastException());
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/google/firebase/messaging/FirebaseMessagingService.kt:
--------------------------------------------------------------------------------
1 | package com.google.firebase.messaging
2 |
3 | import android.content.Context
4 |
5 | object FirebaseMessagingServiceTestContext {
6 | var appContext: Context? = null
7 | }
8 |
9 | open class FirebaseMessagingService {
10 | var applicationContext: Context?
11 | get() = FirebaseMessagingServiceTestContext.appContext
12 | set(value) {
13 | FirebaseMessagingServiceTestContext.appContext = value
14 | }
15 |
16 | open fun onNewToken(token: String?) {}
17 | }
18 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/AccessUtils.java:
--------------------------------------------------------------------------------
1 | package com.mparticle;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 | import android.os.Message;
6 |
7 | import androidx.annotation.RequiresApi;
8 |
9 | import com.mparticle.identity.BaseIdentityTask;
10 | import com.mparticle.internal.KitFrameworkWrapper;
11 | import com.mparticle.internal.MPUtility;
12 | import com.mparticle.internal.MessageManager;
13 |
14 | import java.util.Set;
15 |
16 | public class AccessUtils {
17 |
18 | public static void reset(Context context, boolean deleteDatabase, boolean switchingWorkspaces) {
19 | MParticle.reset(context, deleteDatabase, switchingWorkspaces);
20 | }
21 |
22 | public static MessageManager getMessageManager() {
23 | return MParticle.getInstance().mMessageManager;
24 | }
25 |
26 | public static void setKitManager(KitFrameworkWrapper kitManager) {
27 | MParticle.getInstance().mKitManager = kitManager;
28 | }
29 |
30 | public static BaseIdentityTask getIdentityTask(MParticleOptions.Builder builder) {
31 | return builder.identityTask;
32 | }
33 |
34 | public static MParticleOptions.Builder setCredentialsIfEmpty(MParticleOptions.Builder builder) {
35 | if (MPUtility.isEmpty(builder.apiKey) && MPUtility.isEmpty(builder.apiSecret)) {
36 | builder.credentials("key", "secret");
37 | }
38 | return builder;
39 | }
40 |
41 | public static MParticleOptions emptyMParticleOptions(Context context) {
42 | return MParticleOptions.builder(context).buildForInternalRestart();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/LegacyOnly.java:
--------------------------------------------------------------------------------
1 | package com.mparticle;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Target({ElementType.METHOD, ElementType.TYPE})
9 | @Retention(RetentionPolicy.RUNTIME)
10 | public @interface LegacyOnly {
11 | }
12 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/OrchestratorOnly.java:
--------------------------------------------------------------------------------
1 | package com.mparticle;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Target({ElementType.METHOD, ElementType.TYPE})
9 | @Retention(RetentionPolicy.RUNTIME)
10 | public @interface OrchestratorOnly {
11 | }
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/mock/MockApplication.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.mock;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 | import android.content.pm.ApplicationInfo;
7 | import android.content.pm.PackageManager;
8 | import android.content.res.Resources;
9 |
10 | import java.io.File;
11 |
12 | /**
13 | * Created by sdozor on 4/10/15.
14 | */
15 | public class MockApplication extends Application {
16 | MockContext mContext;
17 | public ActivityLifecycleCallbacks mCallbacks;
18 |
19 | public MockApplication(MockContext context) {
20 | super();
21 | mContext = context;
22 | }
23 |
24 | @Override
25 | public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
26 | mCallbacks = callback;
27 | }
28 |
29 | @Override
30 | public Context getApplicationContext() {
31 | return this;
32 | }
33 |
34 | public void setSharedPreferences(SharedPreferences prefs) {
35 | mContext.setSharedPreferences(prefs);
36 | }
37 |
38 | @Override
39 | public Object getSystemService(String name) {
40 | return mContext.getSystemService(name);
41 | }
42 |
43 | @Override
44 | public SharedPreferences getSharedPreferences(String name, int mode) {
45 | return mContext.getSharedPreferences(name, mode);
46 | }
47 |
48 | @Override
49 | public PackageManager getPackageManager() {
50 | return mContext.getPackageManager();
51 | }
52 |
53 | @Override
54 | public String getPackageName() {
55 | return mContext.getPackageName();
56 | }
57 |
58 | @Override
59 | public ApplicationInfo getApplicationInfo() {
60 | return mContext.getApplicationInfo();
61 | }
62 |
63 | @Override
64 | public Resources getResources() {
65 | return mContext.getResources();
66 | }
67 |
68 | @Override
69 | public File getFilesDir() {
70 | return mContext.getFilesDir();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/mock/MockConfigManager.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.mock;
2 |
3 |
4 | import com.mparticle.MParticle;
5 | import com.mparticle.internal.ConfigManager;
6 |
7 | public class MockConfigManager extends ConfigManager {
8 | public MockConfigManager() {
9 | super(new MockContext(), MParticle.Environment.Production, null, null, null, null, null, null, null, null);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/mock/MockCoreCallbacks.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.mock;
2 |
3 | import android.app.Activity;
4 | import android.net.Uri;
5 |
6 | import com.mparticle.MParticleOptions;
7 | import com.mparticle.internal.CoreCallbacks;
8 |
9 | import org.json.JSONArray;
10 |
11 | import java.lang.ref.WeakReference;
12 | import java.util.Map;
13 |
14 | public class MockCoreCallbacks implements CoreCallbacks {
15 |
16 | @Override
17 | public boolean isBackgrounded() {
18 | return false;
19 | }
20 |
21 | @Override
22 | public int getUserBucket() {
23 | return 0;
24 | }
25 |
26 | @Override
27 | public boolean isEnabled() {
28 | return false;
29 | }
30 |
31 | @Override
32 | public void setIntegrationAttributes(int kitId, Map integrationAttributes) {
33 |
34 | }
35 |
36 | @Override
37 | public Map getIntegrationAttributes(int kitId) {
38 | return null;
39 | }
40 |
41 | @Override
42 | public WeakReference getCurrentActivity() {
43 | return null;
44 | }
45 |
46 | @Override
47 | public JSONArray getLatestKitConfiguration() {
48 | return null;
49 | }
50 |
51 | @Override
52 | public MParticleOptions.DataplanOptions getDataplanOptions() {
53 | return null;
54 | }
55 |
56 | @Override
57 | public boolean isPushEnabled() {
58 | return false;
59 | }
60 |
61 | @Override
62 | public String getPushSenderId() {
63 | return null;
64 | }
65 |
66 | @Override
67 | public String getPushInstanceId() {
68 | return null;
69 | }
70 |
71 | @Override
72 | public Uri getLaunchUri() {
73 | return null;
74 | }
75 |
76 | @Override
77 | public String getLaunchAction() {
78 | return null;
79 | }
80 |
81 | @Override
82 | public KitListener getKitListener() {
83 | return KitListener.EMPTY;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/mock/MockKit.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.mock;
2 |
3 | import android.content.Context;
4 |
5 | import com.mparticle.kits.KitIntegration;
6 | import com.mparticle.kits.ReportingMessage;
7 |
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 |
12 | public class MockKit extends KitIntegration {
13 | @Override
14 | public String getName() {
15 | return "Mock Kit";
16 | }
17 |
18 | @Override
19 | protected List onKitCreate(Map settings, Context context) {
20 | return null;
21 | }
22 |
23 | @Override
24 | public List setOptOut(boolean optedOut) {
25 | return null;
26 | }
27 |
28 | @Override
29 | public boolean isDisabled() {
30 | return false;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/mock/MockKitIntegrationFactory.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.mock;
2 |
3 | import com.mparticle.MParticleOptions;
4 | import com.mparticle.kits.KitIntegration;
5 | import com.mparticle.kits.KitIntegrationFactory;
6 | import com.mparticle.kits.KitManagerImpl;
7 |
8 | import org.json.JSONException;
9 |
10 | public class MockKitIntegrationFactory extends KitIntegrationFactory {
11 |
12 | public MockKitIntegrationFactory(MParticleOptions options) {
13 | super(options);
14 | }
15 |
16 | @Override
17 | public boolean isSupported(int kitModuleId) {
18 | return true;
19 | }
20 |
21 | @Override
22 | public KitIntegration createInstance(KitManagerImpl manager, int moduleId) throws JSONException, ClassNotFoundException {
23 | return new MockKit().setKitManager(manager);
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/mock/MockKitManagerImpl.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.mock;
2 |
3 | import android.content.Context;
4 |
5 | import com.mparticle.MParticleOptions;
6 | import com.mparticle.internal.CoreCallbacks;
7 | import com.mparticle.internal.ReportingManager;
8 | import com.mparticle.kits.KitConfiguration;
9 | import com.mparticle.kits.KitManagerImpl;
10 |
11 | import org.json.JSONException;
12 | import org.json.JSONObject;
13 | import org.mockito.Mockito;
14 |
15 | public class MockKitManagerImpl extends KitManagerImpl {
16 |
17 | public MockKitManagerImpl() {
18 | this(new MockContext(), Mockito.mock(ReportingManager.class), Mockito.mock(CoreCallbacks.class));
19 | Mockito.when(mCoreCallbacks.getKitListener()).thenReturn(CoreCallbacks.KitListener.EMPTY);
20 | }
21 |
22 | public MockKitManagerImpl(Context context, ReportingManager reportingManager, CoreCallbacks coreCallbacks) {
23 | super(context, reportingManager, coreCallbacks, Mockito.mock(MParticleOptions.class));
24 | }
25 |
26 | public MockKitManagerImpl(MParticleOptions options) {
27 | super(new MockContext(), Mockito.mock(ReportingManager.class), Mockito.mock(CoreCallbacks.class), options);
28 | Mockito.when(mCoreCallbacks.getKitListener()).thenReturn(CoreCallbacks.KitListener.EMPTY);
29 | }
30 |
31 | @Override
32 | protected KitConfiguration createKitConfiguration(JSONObject configuration) throws JSONException {
33 | return MockKitConfiguration.createKitConfiguration(configuration);
34 | }
35 |
36 | @Override
37 | public int getUserBucket() {
38 | return 50;
39 | }
40 |
41 | @Override
42 | public void runOnKitThread(Runnable runnable) {
43 | runnable.run();
44 | }
45 |
46 | @Override
47 | public void runOnMainThread(Runnable runnable) {
48 | runnable.run();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/mock/MockMParticle.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.mock;
2 |
3 | import com.mparticle.MParticle;
4 | import com.mparticle.identity.IdentityApi;
5 | import com.mparticle.internal.ConfigManager;
6 | import com.mparticle.internal.KitFrameworkWrapper;
7 | import com.mparticle.internal.MessageManager;
8 | import com.mparticle.media.MPMediaAPI;
9 | import com.mparticle.messaging.MPMessagingAPI;
10 |
11 | import org.mockito.Mockito;
12 |
13 | import java.util.Random;
14 |
15 | public class MockMParticle extends MParticle {
16 |
17 | public MockMParticle() {
18 | mConfigManager = Mockito.mock(ConfigManager.class);
19 | Mockito.when(mConfigManager.getMpid()).thenReturn(new Random().nextLong());
20 | mKitManager = Mockito.mock(KitFrameworkWrapper.class);
21 | mMessageManager = Mockito.mock(MessageManager.class);
22 | mMessaging = Mockito.mock(MPMessagingAPI.class);
23 | mMedia = Mockito.mock(MPMediaAPI.class);
24 | mIdentityApi = new IdentityApi(new MockContext(), mAppStateManager, mMessageManager, Internal().getConfigManager(), mKitManager, OperatingSystem.ANDROID);
25 | mPreferences = new MockSharedPreferences();
26 | }
27 |
28 | public void setIdentityApi(IdentityApi identityApi) {
29 | this.mIdentityApi = identityApi;
30 | }
31 |
32 | class MockInternal extends Internal {
33 |
34 | MockInternal() {
35 | super();
36 | }
37 | }
38 |
39 | class MockRokt extends Rokt {
40 |
41 | MockRokt() {
42 | super();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/mock/MockResources.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.mock;
2 |
3 | import android.content.res.Resources;
4 |
5 | /**
6 | * Created by sdozor on 3/23/15.
7 | */
8 | public class MockResources extends Resources {
9 | public static String TEST_APP_KEY = "the app key";
10 | public static String TEST_APP_SECRET = "the app secret";
11 |
12 |
13 | public MockResources() {
14 | super(null, null, null);
15 | }
16 |
17 | @Override
18 | public int getIdentifier(String name, String defType, String defPackage) {
19 | if (name.equals("mp_key")) {
20 | return 1;
21 | } else if (name.equals("mp_secret")) {
22 | return 2;
23 | }
24 |
25 | return 0;
26 | }
27 |
28 | @Override
29 | public String getString(int id) throws NotFoundException {
30 | switch (id) {
31 | case 1:
32 | return TEST_APP_KEY;
33 | case 2:
34 | return TEST_APP_SECRET;
35 |
36 | }
37 | return null;
38 | }
39 |
40 | @Override
41 | public String getString(int id, Object... formatArgs) throws NotFoundException {
42 | return super.getString(id, formatArgs);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/networking/CallbackResponse.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 |
6 | public class CallbackResponse {
7 | public final MockServer.RequestReceivedCallback callback;
8 |
9 | public CallbackResponse(MockServer.RequestReceivedCallback callback) {
10 | this.callback = callback;
11 | }
12 |
13 | public void invokeCallback(final MPConnectionTestImpl connection) {
14 | new Handler(Looper.getMainLooper()).post(new Runnable() {
15 |
16 | public void run() {
17 | callback.onRequestReceived(new Request(connection));
18 | }
19 | });
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/networking/MPUrlTestImpl.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class MPUrlTestImpl extends MPUrl {
7 | String url;
8 |
9 | public MPUrlTestImpl(String url) {
10 | this.url = url;
11 | }
12 |
13 | @Override
14 | public MPConnection openConnection() {
15 | return new MPConnectionTestImpl(this);
16 | }
17 |
18 | @Override
19 | public String getFile() {
20 | return url;
21 | }
22 |
23 | @Override
24 | public String getAuthority() {
25 | try {
26 | return new URL(url).getAuthority();
27 | } catch (MalformedURLException e) {
28 | return null;
29 | }
30 | }
31 |
32 | @Override
33 | public String getPath() {
34 | try {
35 | return new URL(url).getPath();
36 | } catch (MalformedURLException e) {
37 | return null;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/networking/Matcher.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | import org.json.JSONObject;
4 |
5 | public class Matcher {
6 |
7 | public Matcher() {
8 | }
9 |
10 | public Matcher(MPUrl url) {
11 | this.url = url.getFile();
12 | }
13 |
14 | String url;
15 | MockServer.UrlMatcher urlMatcher;
16 | MockServer.JSONMatch bodyMatch;
17 | boolean keepAfterMatch;
18 | Long timestamp = System.currentTimeMillis();
19 |
20 | boolean isMatch(MPConnectionTestImpl mockConnection) {
21 | if (url != null) {
22 | if (!url.equals(mockConnection.getURL().getFile())) {
23 | return false;
24 | }
25 | }
26 | if (urlMatcher != null) {
27 | if (!urlMatcher.isMatch(mockConnection.getURL())) {
28 | return false;
29 | }
30 | }
31 | if (bodyMatch != null) {
32 | try {
33 | if (!bodyMatch.isMatch(new JSONObject(mockConnection.getBody()))) {
34 | return false;
35 | }
36 | } catch (Throwable e) {
37 | throw new Error(e);
38 | }
39 | }
40 | return true;
41 | }
42 |
43 | public Matcher bodyMatch(MockServer.JSONMatch jsonMatch) {
44 | this.bodyMatch = jsonMatch;
45 | return this;
46 | }
47 |
48 | public Matcher urlMatcher(MockServer.UrlMatcher urlMatcher) {
49 | this.urlMatcher = urlMatcher;
50 | return this;
51 | }
52 |
53 | @Override
54 | public boolean equals(Object obj) {
55 | if (obj instanceof Matcher) {
56 | Matcher matcher = (Matcher) obj;
57 |
58 | if (matcher.bodyMatch == bodyMatch &&
59 | matcher.url == url &&
60 | matcher.urlMatcher == urlMatcher) {
61 | return true;
62 | }
63 | }
64 | return false;
65 | }
66 | }
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/networking/Request.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | import org.json.JSONException;
4 | import org.json.JSONObject;
5 |
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 | public class Request {
10 | Map> headers;
11 | String url;
12 | String body;
13 | MPConnection connection;
14 |
15 | Request(MPConnectionTestImpl connection) {
16 | headers = connection.getHeaderFields();
17 | url = connection.getURL().getFile();
18 | body = connection.getBody();
19 | this.connection = connection;
20 | }
21 |
22 | Request(Request request) {
23 | headers = request.headers;
24 | url = request.url;
25 | body = request.body;
26 | connection = request.connection;
27 | }
28 |
29 | MPConnection getConnection() {
30 | return connection;
31 | }
32 |
33 | public JSONObject getBodyJson() {
34 | try {
35 | return new JSONObject(body);
36 | } catch (JSONException e) {
37 | throw new RuntimeException(e);
38 | }
39 | }
40 |
41 | public IdentityRequest asIdentityRequest() {
42 | return new IdentityRequest(this);
43 | }
44 |
45 | public String getUrl() {
46 | return url;
47 | }
48 |
49 | public Map> getHeaders() {
50 | return headers;
51 | }
52 | }
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/networking/Response.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.networking;
2 |
3 | class Response {
4 |
5 | int responseCode = 200;
6 | String responseBody = "";
7 | long delay;
8 |
9 | Response() {
10 | }
11 |
12 | Response(String responseBody) {
13 | this(200, responseBody);
14 | }
15 |
16 | Response(int responseCode, String responseBody) {
17 | this.responseCode = responseCode;
18 | this.responseBody = responseBody;
19 | }
20 |
21 | MockServer.OnRequestCallback onRequestCallback;
22 |
23 | void setRequest(MPConnectionTestImpl connection) {
24 | if (onRequestCallback != null) {
25 | onRequestCallback.onRequest(this, connection);
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/testutils/AndroidUtils.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.testutils;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.content.ContextWrapper;
6 | import android.content.pm.ApplicationInfo;
7 |
8 | import com.mparticle.internal.ApplicationContextWrapper;
9 |
10 | /**
11 | * Utility methods for manipulating the Android sdk state for testing purposes.
12 | */
13 | public class AndroidUtils {
14 |
15 | public static Context getProductionContext(final Context context) {
16 | return new ContextWrapper(context) {
17 | @Override
18 | public ApplicationInfo getApplicationInfo() {
19 | ApplicationInfo applicationInfo = new ApplicationInfo();
20 | applicationInfo.flags = 0;
21 | return applicationInfo;
22 | }
23 |
24 | @Override
25 | public Context getApplicationContext() {
26 | return new ApplicationContextWrapper((Application) context.getApplicationContext()) {
27 | @Override
28 | public ApplicationInfo getApplicationInfo() {
29 | ApplicationInfo applicationInfo = new ApplicationInfo();
30 | applicationInfo.flags = 0;
31 | return applicationInfo;
32 | }
33 | };
34 | }
35 | };
36 | }
37 |
38 | public static class Mutable {
39 | public T value;
40 |
41 | public Mutable(T value) {
42 | this.value = value;
43 | }
44 | }
45 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/testutils/AssertObject.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.testutils;
2 |
3 | public abstract class AssertObject implements StreamAssert.Assert {
4 | @Override
5 | public boolean assertTrueI(T object) {
6 | return true;
7 | }
8 | }
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/testutils/AssertTrue.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.testutils;
2 |
3 | public abstract class AssertTrue implements StreamAssert.Assert {
4 | @Override
5 | public void assertObject(T object) {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/testutils/BaseCleanInstallEachTest.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.testutils;
2 |
3 | import org.junit.Before;
4 |
5 | /**
6 | * Base class that will replicate the scenario or an app that has started, but has not called
7 | * MParticle.start(). This base class is useful for testing initialization behavior.
8 | */
9 | abstract public class BaseCleanInstallEachTest extends BaseAbstractTest {
10 |
11 | @Before
12 | public void beforeBase() throws Exception {
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/testutils/BaseCleanStartedEachTest.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.testutils;
2 |
3 | import com.mparticle.MParticle;
4 | import com.mparticle.MParticleOptions;
5 | import com.mparticle.identity.IdentityApiRequest;
6 | import com.mparticle.internal.AppStateManager;
7 |
8 | import org.jetbrains.annotations.NotNull;
9 | import org.junit.Before;
10 |
11 |
12 | /**
13 | * Base class that will replicate the scenario that MParticle has been started and is running. This
14 | * state also includes the initial IdentityApi.Identify call has completed.
15 | *
16 | * That being said, there is no need to call MParticle.start() in your before or beforeClass methods,
17 | * or in your tests.
18 | *
19 | * If you want to test the behavior that occurs during initialization, you should either invoke
20 | * MParticle.setInstance(null), or use BaseCleanInstallEachTest as your base class.
21 | */
22 | public class BaseCleanStartedEachTest extends BaseAbstractTest {
23 |
24 | public void beforeSetup() {
25 | }
26 |
27 | @Before
28 | public final void beforeBase() throws InterruptedException {
29 | if (MParticle.getInstance() != null) {
30 | MParticle.reset(mContext);
31 | }
32 | MParticle.setInstance(null);
33 | beforeSetup();
34 | startMParticle(transformMParticleOptions(getBaseMParticleOptionBuilder()));
35 | AppStateManager.mInitialized = false;
36 | }
37 |
38 | protected MParticleOptions.Builder getBaseMParticleOptionBuilder() {
39 | return MParticleOptions
40 | .builder(mContext)
41 | .credentials("key", "value")
42 | .identify(IdentityApiRequest.withEmptyUser().build())
43 | .environment(MParticle.Environment.Production);
44 | }
45 |
46 | protected void restartWithOptions(@NotNull MParticleOptions.Builder options) throws InterruptedException {
47 | startMParticle(options);
48 | }
49 |
50 | //Override this if you need to do something simple like add or remove a network options before.
51 | //Just don't mess with the "identitfyTask" that will break things
52 | protected MParticleOptions.Builder transformMParticleOptions(MParticleOptions.Builder builder) {
53 | return builder;
54 | }
55 | }
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/testutils/MPLatch.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.testutils;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 |
6 | import java.util.concurrent.CountDownLatch;
7 | import java.util.concurrent.TimeUnit;
8 |
9 | public class MPLatch extends CountDownLatch {
10 | int countDowned = 0;
11 | int count;
12 | Handler mHandler;
13 | AndroidUtils.Mutable timedOut = new AndroidUtils.Mutable<>(false);
14 | Runnable timeoutRunnable = new Runnable() {
15 | @Override
16 | public void run() {
17 | timedOut.value = true;
18 | }
19 | };
20 |
21 | /**
22 | * Constructs a {@code CountDownLatch} initialized with the given count.
23 | *
24 | * @param count the number of times {@link #countDown} must be invoked
25 | * before threads can pass through {@link #await}
26 | * @throws IllegalArgumentException if {@code count} is negative
27 | */
28 | public MPLatch(int count) {
29 | super(count);
30 | this.count = count;
31 | mHandler = new Handler(Looper.getMainLooper());
32 | }
33 |
34 | public MPLatch() {
35 | super(1);
36 | mHandler = new Handler();
37 | }
38 |
39 | @Override
40 | public void countDown() {
41 | synchronized (this) {
42 | countDowned++;
43 | if (countDowned == count) {
44 | mHandler.removeCallbacks(timeoutRunnable);
45 | }
46 | super.countDown();
47 | }
48 | }
49 |
50 | @Override
51 | public void await() throws InterruptedException {
52 | int timeoutTimeMs = 5 * 1000;
53 | synchronized (this) {
54 | if (count == countDowned) {
55 | return;
56 | }
57 | }
58 | this.await(timeoutTimeMs, TimeUnit.MILLISECONDS);
59 | mHandler.postDelayed(timeoutRunnable, timeoutTimeMs - 100L);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/testutils/TestingContext.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.testutils;
2 |
3 | import android.content.Context;
4 | import android.content.ContextWrapper;
5 | import android.content.pm.PackageManager;
6 |
7 | public class TestingContext extends ContextWrapper {
8 | TestingContext(Context context) {
9 | super(context);
10 | }
11 |
12 | @Override
13 | public int checkCallingOrSelfPermission(String permission) {
14 | if (permission.equals("com.google.android.c2dm.permission.RECEIVE")) {
15 | return PackageManager.PERMISSION_GRANTED;
16 | }
17 | return super.checkCallingOrSelfPermission(permission);
18 | }
19 | }
--------------------------------------------------------------------------------
/testutils/src/main/java/com/mparticle/testutils/TestingUncaughtExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.mparticle.testutils;
2 |
3 | import android.os.Handler;
4 |
5 | import androidx.annotation.NonNull;
6 |
7 | public class TestingUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
8 |
9 | Handler testHandler = new Handler();
10 |
11 | @Override
12 | public void uncaughtException(@NonNull Thread t, @NonNull final Throwable e) {
13 | if (t.getName().equals("mParticleMessageHandler") || t.getName().equals("mParticleUploadHandler")) {
14 | testHandler.post(new Runnable() {
15 | @Override
16 | public void run() {
17 | throw new RuntimeException(e);
18 | }
19 | });
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/testutils/src/main/kotlin/com.mparticle/Utils.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | import com.mparticle.commerce.Product
4 | import com.mparticle.commerce.Promotion
5 | import java.lang.reflect.Modifier
6 | import kotlin.random.Random
7 |
8 | object Utils {
9 |
10 | fun randomPromotionAction(): String {
11 | return randomConstString(Promotion::class.java)
12 | }
13 |
14 | fun randomConstString(clazz: Class<*>): String {
15 | return clazz.fields
16 | .filter { Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) }
17 | .filter { it.name.all { it.isUpperCase() } }
18 | .filter { it.type == String::class.java }
19 | .let {
20 | it[Random.Default.nextInt(0, it.size - 1)].get(null) as String
21 | }
22 | }
23 |
24 | val chars: List = ('a'..'z') + ('A'..'Z')
25 |
26 | fun randomAttributes(): MutableMap {
27 | return (0..Random.Default.nextInt(0, 5)).map {
28 | randomString(4) to randomString(8)
29 | }.toMap().toMutableMap()
30 | }
31 |
32 | fun randomIdentities(): MutableMap {
33 | val identities = MParticle.IdentityType.values()
34 | return (0..Random.Default.nextInt(3, 8)).map {
35 | identities[Random.Default.nextInt(0, identities.size - 1)] to randomString(8)
36 | }.toMap().toMutableMap()
37 | }
38 |
39 | fun randomString(length: Int): String {
40 | return (0..length - 1).map {
41 | chars[Random.Default.nextInt(0, chars.size - 1)]
42 | }.joinToString("")
43 | }
44 |
45 | fun randomEventType(): MParticle.EventType {
46 | return MParticle.EventType.values()[
47 | Random.Default.nextInt(
48 | 0,
49 | MParticle.EventType.values().size - 1
50 | )
51 | ]
52 | }
53 |
54 | fun randomProductAction(): String {
55 | return randomConstString(Product::class.java)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tooling/android-plugin/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'groovy'
2 | apply plugin: 'kotlin'
3 |
4 | sourceCompatibility = JavaVersion.VERSION_1_8
5 | targetCompatibility = JavaVersion.VERSION_1_8
6 |
7 |
8 | ext {
9 | kitDescription = 'mParticle Gradle Plugin for managing Dataplanning functionality'
10 | }
11 |
12 | apply from: '../../scripts/maven.gradle'
13 |
14 | buildscript {
15 | repositories {
16 | mavenCentral()
17 | }
18 | dependencies {
19 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
20 | }
21 | }
22 |
23 | configurations {
24 | fatJar
25 | }
26 |
27 | dependencies {
28 | fatJar project(':tooling:common')
29 | compileOnly configurations.fatJar
30 | implementation gradleApi()
31 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
32 | implementation files('libs/java-json.jar')
33 | testImplementation 'junit:junit:4.13.2'
34 | testImplementation project(':tooling:common')
35 | }
36 |
37 | jar {
38 | from {
39 | configurations.fatJar.collect { it.isDirectory() ? it : zipTree(it) }
40 | }
41 | }
42 |
43 | task generateJavadocsJar(type: Jar, dependsOn: groovydoc) {
44 | archiveClassifier.set("javadoc")
45 | from groovydoc.destinationDir
46 | }
47 |
48 | task generateSourcesJar(type: Jar) {
49 | archiveClassifier.set("sources")
50 | from sourceSets.main.allJava
51 | }
--------------------------------------------------------------------------------
/tooling/android-plugin/libs/java-json.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mParticle/mparticle-android-sdk/6243d3ce106adc537f7ac9dcff44d7746929e514/tooling/android-plugin/libs/java-json.jar
--------------------------------------------------------------------------------
/tooling/android-plugin/src/main/java/com/mparticle/MParticleExtension.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | open class MParticleExtension {
4 | var dataPlanVersionFile: String? = null
5 | var resultsFile: String? = null
6 |
7 | var disabled: Boolean? = null
8 | var verbose: Boolean? = null
9 | var debugReportServerMessage: Boolean? = null
10 | }
11 |
--------------------------------------------------------------------------------
/tooling/android-plugin/src/main/resources/META-INF/gradle-plugins/com.mparticle.properties:
--------------------------------------------------------------------------------
1 | implementation-class=com.mparticle.MParticlePlugin
--------------------------------------------------------------------------------
/tooling/android-plugin/src/test/java/com/mparticle/MParticlePluginTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle
2 |
3 | import com.mparticle.tooling.Config
4 | import groovy.util.GroovyTestCase.assertEquals
5 | import org.junit.Test
6 |
7 | class MParticlePluginTest {
8 |
9 | @Test
10 | fun testConfigSerialization() {
11 | val config = Config().apply {
12 | this.credentialsFilePath = "credentialsFilePath"
13 | this.dataPlanVersionFile = "dataplanfile"
14 | this.dataPlanId = "dataplanid"
15 | this.dataPlanVersion = "dataplanversion"
16 | this.debugReportServerMessage = true
17 | this.resultsFile = "resultsfilelocation"
18 | this.verbose = null
19 | this.workspaceId = "workspaceId"
20 | this.internalConfig = Config.InternalConfig(
21 | "path/to/node",
22 | "path/to/mp"
23 | )
24 | }
25 | val json = config.toJson()
26 | assertEquals(config, Config.from(json))
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tooling/common/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | }
5 | dependencies {
6 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
7 | }
8 | }
9 |
10 | apply plugin: 'java-library'
11 | apply plugin: 'kotlin'
12 |
13 | dependencies {
14 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
15 | api files('libs/java-json.jar')
16 | }
17 |
18 | java {
19 | sourceCompatibility = JavaVersion.VERSION_1_8
20 | targetCompatibility = JavaVersion.VERSION_1_8
21 | }
--------------------------------------------------------------------------------
/tooling/common/libs/java-json.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mParticle/mparticle-android-sdk/6243d3ce106adc537f7ac9dcff44d7746929e514/tooling/common/libs/java-json.jar
--------------------------------------------------------------------------------
/tooling/common/src/main/java/com/mparticle/tooling/Logger.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.tooling
2 |
3 | object Logger {
4 | var verbose = false
5 |
6 | fun error(message: String) {
7 | println(message)
8 | }
9 |
10 | fun verbose(message: String) {
11 | if (verbose) {
12 | println(message)
13 | }
14 | }
15 |
16 | fun warning(message: String) {
17 | println(message)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tooling/common/src/main/java/com/mparticle/tooling/MockDataPlanningNodeApp.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.tooling
2 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/mparticle-core-proguard.pro:
--------------------------------------------------------------------------------
1 | -dontwarn
2 | -dontusemixedcaseclassnames
3 | -keepattributes InnerClasses
4 |
5 | -keep class com.mparticle.MPEvent { *; }
6 | -keep class com.mparticle.MPEvent$* { *; }
7 | -keep class com.mparticle.commerce.CommerceEvent { *; }
8 | -keep class com.mparticle.commerce.CommerceEvent$* { *; }
9 | -keep class com.mparticle.commerce.Product { *; }
10 | -keep class com.mparticle.commerce.Product$Builder { *; }
11 | -keep class com.mparticle.commerce.Promotion { *; }
12 | -keep class com.mparticle.commerce.TransactionAttributes { *; }
13 | -keep class com.mparticle.commerce.Impression { *; }
14 | -keep class com.mparticle.MParticle$LogLevel { *; }
15 |
16 | -keep class com.mparticle.internal.Logger { *; }
17 | -keep class com.mparticle.internal.Logger$* { *; }
18 |
19 | # -keep class com.mparticle.MParticle$EventType
20 |
21 | -keep enum ** {
22 | *;
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/main/java/com/mparticle/lints/MParticleIssueRegistry.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints
2 |
3 | import com.android.tools.lint.client.api.IssueRegistry
4 | import com.android.tools.lint.client.api.Vendor
5 | import com.android.tools.lint.detector.api.CURRENT_API
6 | import com.mparticle.lints.detectors.DataplanDetector
7 | import com.mparticle.lints.detectors.GradleBuildDetector
8 | import com.mparticle.lints.detectors.MpApiDetectorKt
9 | import com.mparticle.lints.detectors.ReferrerReceiverDetector
10 |
11 | /**
12 | * The list of issues that will be checked when running lint
.
13 | */
14 | @SuppressWarnings("unused")
15 | class MParticleIssueRegistry : IssueRegistry() {
16 | override val issues = listOf(
17 | GradleBuildDetector.ISSUE,
18 | MpApiDetectorKt.ISSUE,
19 | ReferrerReceiverDetector.ISSUE,
20 | DataplanDetector.ISSUE,
21 | DataplanDetector.NODE_MISSING,
22 | DataplanDetector.NO_DATA_PLAN
23 | )
24 |
25 | override val api: Int = CURRENT_API
26 |
27 | override val vendor: Vendor = Vendor(
28 | vendorName = "mParticle",
29 | identifier = "android-core",
30 | feedbackUrl = "https://github.com/mParticle/mparticle-android-sdk"
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/main/java/com/mparticle/lints/basedetectors/BaseDetector.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints.basedetectors
2 |
3 | import com.android.tools.lint.detector.api.Context
4 | import com.android.tools.lint.detector.api.Detector
5 | import com.mparticle.tooling.Config
6 | import com.mparticle.tooling.Logger
7 | import com.mparticle.tooling.Utils
8 |
9 | open class BaseDetector : Detector() {
10 | protected var disabled: Boolean = false
11 | get() = config?.disabled == true || field
12 | set
13 | private var configFile: Config? = null
14 | private var configLastModified = 0L
15 | protected var config: Config?
16 | get() {
17 | val lastModified = Utils.getConfigFileLastModified()
18 | if (configFile == null || lastModified != configLastModified) {
19 | configFile = Utils.getConfigFile()
20 | }
21 | return configFile
22 | }
23 | set(value) {
24 | configFile = value
25 | }
26 |
27 | override fun beforeCheckEachProject(context: Context) {
28 | super.beforeCheckRootProject(context)
29 | Logger.verbose = config?.verbose ?: false
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/main/java/com/mparticle/lints/dtos/Constructor.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints.dtos
2 |
3 | import com.mparticle.lints.receiverClassName
4 | import com.mparticle.lints.resolve
5 | import org.jetbrains.uast.UCallExpression
6 |
7 | data class Constructor(
8 | override val parent: Expression,
9 | val methodName: String?,
10 | override val node: UCallExpression
11 | ) : ParameterizedExpression {
12 | override var arguments: List = listOf()
13 |
14 | override fun resolve(): Any? {
15 | val qualifiedClassName =
16 | node.receiverClassName()?.replace(".Builder", "\$Builder")
17 | val clazz = Class.forName(qualifiedClassName)
18 | val params: List = arguments.resolve()
19 | val argumentClasses = params.map {
20 | if (it != null) {
21 | it::class.java
22 | } else {
23 | Nothing::class.java
24 | }
25 | }
26 | val constructor =
27 | try {
28 | clazz.getConstructor(*argumentClasses.toTypedArray())
29 | } catch (ex: Exception) {
30 | clazz.constructors.firstOrNull() { it.parameterTypes.size == argumentClasses.size }
31 | }
32 | try {
33 | if (constructor != null) {
34 | if (params.size > 0) {
35 | return constructor.newInstance(*params.toTypedArray())
36 | } else {
37 | return constructor.newInstance()
38 | }
39 | }
40 | } catch (ex: Exception) {
41 | "no new Instance for $clazz.name, tried constructor: ${constructor?.name}"
42 | }
43 | return clazz
44 | }
45 |
46 | override fun forEachExpression(predicate: (Expression) -> Unit) {
47 | predicate(this)
48 | arguments.forEach { it.forEachExpression(predicate) }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/main/java/com/mparticle/lints/dtos/Expression.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints.dtos
2 |
3 | import org.jetbrains.uast.UExpression
4 |
5 | interface Expression {
6 | val node: UExpression
7 | val parent: Expression
8 | fun resolve(): Any?
9 | fun forEachExpression(predicate: (Expression) -> Unit)
10 | }
11 |
12 | interface ParameterizedExpression : Expression {
13 | var arguments: List
14 | }
15 |
16 | class RootParent(override val node: UExpression) : Expression {
17 | override val parent: Expression = this
18 |
19 | override fun resolve() = null
20 |
21 | override fun forEachExpression(predicate: (Expression) -> Unit) {}
22 | }
23 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/main/java/com/mparticle/lints/dtos/MethodCall.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints.dtos
2 |
3 | import com.mparticle.lints.resolve
4 | import org.jetbrains.uast.UCallExpression
5 |
6 | data class MethodCall(
7 | override val parent: Expression,
8 | val methodName: String?,
9 | override val node: UCallExpression,
10 | var returnValue: Boolean
11 | ) : ParameterizedExpression {
12 |
13 | override var arguments: List = listOf()
14 |
15 | init {
16 | arguments.forEach { it.parent = this }
17 | }
18 |
19 | override fun resolve(): Any? {
20 | val instance = parent.resolve()
21 | if (instance == null) {
22 | return null
23 | }
24 | var matchingMethods = instance::class.java.methods
25 | .filter { it.name == methodName }
26 | .filter { it.parameterCount == arguments.size }
27 | if (matchingMethods.size == 1) {
28 | val method = matchingMethods.first {
29 | it.parameterTypes.forEachIndexed { i, type ->
30 | val value = arguments[i].value
31 | if (type.name != "null" && value != null && type.name != value::class.java.name) {
32 | false
33 | }
34 | }
35 | true
36 | }
37 | val arguments = arguments.resolve()
38 | val value = method.invoke(instance, *arguments.toTypedArray())
39 | if (returnValue) {
40 | return value
41 | } else {
42 | return instance
43 | }
44 | }
45 | return null
46 | }
47 |
48 | override fun equals(other: Any?): Boolean {
49 | return node.equals((other as? MethodCall)?.node)
50 | }
51 |
52 | override fun hashCode(): Int {
53 | return node.hashCode()
54 | }
55 |
56 | override fun toString(): String {
57 | return "$methodName (${arguments.joinToString("\n")})"
58 | }
59 |
60 | override fun forEachExpression(predicate: (Expression) -> Unit) {
61 | parent.forEachExpression(predicate)
62 | predicate(this)
63 | arguments.forEach {
64 | it.forEachExpression(predicate)
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/main/java/com/mparticle/lints/dtos/StaticFactory.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints.dtos
2 |
3 | import com.intellij.psi.impl.compiled.ClsClassImpl
4 | import com.mparticle.lints.resolve
5 | import org.jetbrains.uast.UCallExpression
6 | import java.lang.reflect.Method
7 |
8 | class StaticFactory(val methodName: String?, override val node: UCallExpression) :
9 | ParameterizedExpression {
10 | override val parent = RootParent(node)
11 | override var arguments: List = listOf()
12 |
13 | override fun resolve(): Any? {
14 | val qualifiedClassName = (node.resolve()?.parent as? ClsClassImpl)?.stub?.qualifiedName
15 | val methods = HashSet()
16 | val clazz = Class.forName(qualifiedClassName)
17 | methods.addAll(clazz.declaredMethods)
18 | var matchingMethods = methods
19 | .filter { it.name == methodName }
20 | .filter { it.parameterCount == arguments.size }
21 | if (matchingMethods.size == 1) {
22 | val method = matchingMethods.first {
23 | it.parameterTypes.forEachIndexed { i, type ->
24 | val value = if (arguments.size > i) arguments.get(i).value else null
25 | if (type.name != "null" && value != null && type.name != value::class.java.name) {
26 | false
27 | }
28 | }
29 | true
30 | }
31 | val arguments = arguments.resolve()
32 | method.isAccessible = true
33 | return method.invoke(null, *arguments.toTypedArray())
34 | }
35 | return null
36 | }
37 |
38 | override fun forEachExpression(predicate: (Expression) -> Unit) {
39 | predicate(this)
40 | arguments.forEach { it.forEachExpression(predicate) }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/main/java/com/mparticle/lints/dtos/Value.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints.dtos
2 |
3 | import com.mparticle.lints.resolveToEnum
4 | import org.jetbrains.uast.UExpression
5 |
6 | data class Value(override var parent: Expression, val value: Any?, override val node: UExpression) :
7 | Expression {
8 |
9 | override fun toString(): String {
10 | return "$value"
11 | }
12 |
13 | override fun resolve(): Any? {
14 | return when (value) {
15 | is Expression -> {
16 | value.resolve()
17 | }
18 | is Pair<*, *> -> value.resolveToEnum()
19 | else -> value
20 | }
21 | }
22 |
23 | override fun forEachExpression(predicate: (Expression) -> Unit) {
24 | predicate(this)
25 | if (value is Expression) {
26 | value.forEachExpression(predicate)
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/test/java/com/mparticle/lints/Constants.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints
2 |
3 | import com.android.tools.lint.checks.infrastructure.LintDetectorTest.java
4 | import org.intellij.lang.annotations.Language
5 |
6 | object Constants {
7 | const val NO_WARNINGS = "No warnings."
8 |
9 | const val ERROR_WARNING_FORMAT = "%d errors, %d warnings"
10 |
11 | fun getErrorWarningMessageString(errors: Int, warnings: Int): String {
12 | return String.format(ERROR_WARNING_FORMAT, errors, warnings)
13 | }
14 |
15 | @Language("JAVA")
16 | const val mparticleStub =
17 | """package com.mparticle;
18 | public class MParticle {
19 | public static void start() {}
20 | }"""
21 |
22 | @Language("JAVA")
23 | const val applicationStub = """
24 | package android.app;
25 | public class Application {
26 | public void onCreate() {}
27 | public void onResume() {}
28 | }"""
29 |
30 | val mParticleStubClass = java(mparticleStub)
31 | val mApplicationStubClass = java(applicationStub)
32 | }
33 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/test/java/com/mparticle/lints/DataplanDetectorTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints
2 |
3 | import com.android.tools.lint.checks.infrastructure.LintDetectorTest
4 | import com.android.tools.lint.checks.infrastructure.TestMode
5 | import com.mparticle.lints.Constants.mParticleStubClass
6 | import com.mparticle.lints.detectors.DataplanDetector
7 | import org.intellij.lang.annotations.Language
8 | import org.junit.Test
9 | import java.io.File
10 |
11 | class DataplanDetectorTest : LintDetectorTest() {
12 |
13 | @Test
14 | fun testCollection() {
15 | val sdkHome = System.getenv("ANDROID_HOME")
16 | ?: "${System.getProperty("user.home")}/Library/Android/sdk"
17 |
18 | @Language("KT")
19 | val source = """
20 | package com.mparticle.lints
21 | import android.app.Application
22 | import com.mparticle.MParticle
23 | class HasProperCall : Application() {
24 | override fun onCreate() {
25 | super.onCreate()
26 | var attributes = mapOf("this" to "that")
27 | }
28 | }
29 | """
30 | lint()
31 | .sdkHome(File(sdkHome))
32 | .files(kotlin(source), mParticleStubClass)
33 | .skipTestModes(TestMode.PARENTHESIZED)
34 | .run()
35 | .expectErrorCount(0)
36 | }
37 |
38 | override fun requireCompileSdk() = false
39 | override fun getDetector() = DataplanDetector()
40 | override fun getIssues() =
41 | listOf(DataplanDetector.ISSUE, DataplanDetector.NODE_MISSING, DataplanDetector.NO_DATA_PLAN)
42 | }
43 |
--------------------------------------------------------------------------------
/tooling/custom-lint-rules/src/test/java/com/mparticle/lints/ValidationResultDeserializationTest.kt:
--------------------------------------------------------------------------------
1 | package com.mparticle.lints
2 |
3 | import com.mparticle.tooling.ValidationResult
4 | import org.intellij.lang.annotations.Language
5 | import org.json.JSONArray
6 | import org.junit.Assert.assertEquals
7 | import org.junit.Test
8 |
9 | class ValidationResultDeserializationTest {
10 |
11 | @Test
12 | fun testDeserializeValidationResult() {
13 | @Language("JSON")
14 | val serialized = """
15 | [
16 | {
17 | "event_type": "validation_result",
18 | "data": {
19 | "match": {
20 | "type": "custom_event",
21 | "criteria": {
22 | "event_name": "testEvent1",
23 | "custom_event_type": "Other"
24 | }
25 | },
26 | "validation_errors": [
27 | {
28 | "validation_error_type": "unplanned",
29 | "key": "testEvent1",
30 | "error_pointer": "#"
31 | }
32 | ]
33 | }
34 | }
35 | ]
36 | """.trimIndent()
37 |
38 | val validationResult = ValidationResult.from(JSONArray(serialized), listOf(""))
39 | assertEquals(1, validationResult.size)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------