diff --git a/app/build.gradle b/app/build.gradle
index f3bb5b9bd27e..05f7d4af1b58 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -13,6 +13,16 @@ buildscript {
classpath "org.jacoco:org.jacoco.report:$jacoco_version"
classpath "org.jacoco:org.jacoco.agent:$jacoco_version"
}
+
+ //NMC Customization
+ allprojects {
+ repositories {
+ jcenter()
+ maven {
+ url "https://maven.tealiumiq.com/android/releases/"
+ }
+ }
+ }
}
plugins {
@@ -88,6 +98,10 @@ android {
buildConfigField 'boolean', 'CI', ciBuild.toString()
buildConfigField 'boolean', 'RUNTIME_PERF_ANALYSIS', perfAnalysis.toString()
+ //NMC customization
+ buildConfigField "String", "ADJUST_APP_TOKEN", "${ADJUST_APP_TOKEN}"
+ buildConfigField "String", "MOENGAGE_APP_ID", "${MOENGAGE_APP_ID}"
+
javaCompileOptions {
annotationProcessorOptions {
arguments += ["room.schemaLocation": "$projectDir/schemas".toString()]
@@ -379,6 +393,20 @@ dependencies {
kapt "androidx.room:room-compiler:$roomVersion"
androidTestImplementation "androidx.room:room-testing:$roomVersion"
+ //Adjust SDK --> https://github.com/adjust/android_sdk
+ implementation 'com.adjust.sdk:adjust-android:4.28.1'
+ implementation 'com.android.installreferrer:installreferrer:2.2'
+ //google play services identifier required for Adjust SDK
+ implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0'
+
+ //tealium sdk
+ implementation 'com.tealium:library:5.8.0'
+
+ //MoEngage SDK
+ implementation 'com.moengage:moe-android-sdk:11.3.01'
+ //lifecycle required for MoEngage SDK
+ implementation 'androidx.lifecycle:lifecycle-process:2.2.0'
+
implementation "io.coil-kt:coil:2.4.0"
//splash screen dependency ref: https://developer.android.com/develop/ui/views/launch/splash-screen/migrate
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index cb3523a3dc90..1c48729b74bd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -479,6 +479,17 @@
android:name="com.nextcloud.client.etm.EtmActivity"
android:exported="false"
android:theme="@style/Theme.ownCloud.Toolbar" />
+
+
+
+
+
+
+
+
androidInjector() {
return dispatchingAndroidInjector;
}
+ //NMC Customization
+ private void initMarketTrackingSdks(){
+ TealiumSdkUtils.initialiseTealiumSDK(this);
+ AdjustSdkUtils.initialiseAdjustSDK(this);
+ MoEngageSdkUtils.initMoEngageSDK(this);
+ }
public static void setAppTheme(DarkMode mode) {
switch (mode) {
diff --git a/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java b/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java
index 777b3214a323..5d237d7b56a8 100644
--- a/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java
+++ b/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java
@@ -86,6 +86,8 @@
import com.nextcloud.client.onboarding.OnboardingService;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.java.util.Optional;
+import com.nmc.android.marketTracking.AdjustSdkUtils;
+import com.nmc.android.marketTracking.TealiumSdkUtils;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.databinding.AccountSetupBinding;
@@ -1205,6 +1207,10 @@ public void onAuthenticatorTaskCallback(RemoteOperationResult result)
}
private void endSuccess() {
+ //track successful login event
+ AdjustSdkUtils.trackEvent(AdjustSdkUtils.EVENT_TOKEN_SUCCESSFUL_LOGIN, preferences);
+ TealiumSdkUtils.trackEvent(TealiumSdkUtils.EVENT_SUCCESSFUL_LOGIN, preferences);
+
if (onlyAdd) {
finish();
} else {
@@ -1541,4 +1547,11 @@ public void onSavedCertificate() {
public void onFailedSavingCertificate() {
DisplayUtils.showSnackMessage(this, R.string.ssl_validator_not_saved);
}
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ //track screen view when activity is visible
+ TealiumSdkUtils.trackView(TealiumSdkUtils.SCREEN_VIEW_LOGIN, preferences);
+ }
}
diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
index dcbfde829a8c..acd94bcac1c1 100644
--- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
+++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
@@ -68,6 +68,7 @@
import com.nextcloud.client.network.ConnectivityService;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.utils.IntentUtil;
+import com.nmc.android.marketTracking.TealiumSdkUtils;
import com.nextcloud.java.util.Optional;
import com.nextcloud.utils.view.FastScrollUtils;
import com.owncloud.android.MainApp;
@@ -2434,6 +2435,9 @@ public void onStart() {
EventBus.getDefault().post(new TokenPushEvent());
checkForNewDevVersionNecessary(getApplicationContext());
+
+ //track screen view when activity is visible
+ TealiumSdkUtils.trackView(TealiumSdkUtils.SCREEN_VIEW_FILE_BROWSER, preferences);
}
@Override
diff --git a/app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java
index 3971756f67b7..06ae9bc392a8 100644
--- a/app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java
+++ b/app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java
@@ -58,6 +58,7 @@
import com.nextcloud.client.network.ClientFactory;
import com.nextcloud.client.network.ConnectivityService;
import com.nextcloud.client.preferences.AppPreferences;
+import com.nmc.android.marketTracking.TealiumSdkUtils;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.nextcloud.client.preferences.DarkMode;
import com.owncloud.android.BuildConfig;
@@ -1049,6 +1050,13 @@ protected void onPostCreate(Bundle savedInstanceState) {
getDelegate().onPostCreate(savedInstanceState);
}
+ @Override
+ protected void onStart() {
+ super.onStart();
+ //track screen view when activity is visible
+ TealiumSdkUtils.trackView(TealiumSdkUtils.SCREEN_VIEW_SETTINGS, preferences);
+ }
+
@Override
protected void onDestroy() {
super.onDestroy();
diff --git a/app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt
index ea755b52b37d..5021816db8ae 100644
--- a/app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt
+++ b/app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt
@@ -44,6 +44,8 @@ import com.nextcloud.client.jobs.BackgroundJobManager
import com.nextcloud.client.jobs.MediaFoldersDetectionWork
import com.nextcloud.client.jobs.NotificationWork
import com.nextcloud.client.preferences.AppPreferences
+import com.nmc.android.marketTracking.AdjustSdkUtils
+import com.nmc.android.marketTracking.TealiumSdkUtils
import com.owncloud.android.BuildConfig
import com.owncloud.android.MainApp
import com.owncloud.android.R
@@ -577,6 +579,9 @@ class SyncedFoldersActivity :
backgroundJobManager.startImmediateFilesSyncJob(skipCustomFolders = false, overridePowerSaving = false)
showBatteryOptimizationInfo()
}
+
+ //track event when user enable/disable auto upload on/off
+ trackAutoUploadEvent(syncedFolderDisplayItem.isEnabled)
}
override fun onSyncFolderSettingsClick(section: Int, syncedFolderDisplayItem: SyncedFolderDisplayItem) {
@@ -684,6 +689,14 @@ class SyncedFoldersActivity :
if (syncedFolder.isEnabled) {
showBatteryOptimizationInfo()
}
+
+ //track event when user enable/disable auto upload on/off
+ trackAutoUploadEvent(syncedFolder.isEnabled)
+ }
+
+ private fun trackAutoUploadEvent(enabled: Boolean) {
+ AdjustSdkUtils.trackEvent(if (enabled) AdjustSdkUtils.EVENT_TOKEN_SETTINGS_AUTO_UPLOAD_ON else AdjustSdkUtils.EVENT_TOKEN_SETTINGS_AUTO_UPLOAD_OFF, preferences)
+ TealiumSdkUtils.trackEvent(if (enabled) TealiumSdkUtils.EVENT_SETTINGS_AUTO_UPLOAD_ON else TealiumSdkUtils.EVENT_SETTINGS_AUTO_UPLOAD_OFF, preferences)
}
private fun saveOrUpdateSyncedFolder(item: SyncedFolderDisplayItem) {
diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/AccountRemovalConfirmationDialog.java b/app/src/main/java/com/owncloud/android/ui/dialog/AccountRemovalConfirmationDialog.java
index f2863b19755e..1bddb9ec307c 100644
--- a/app/src/main/java/com/owncloud/android/ui/dialog/AccountRemovalConfirmationDialog.java
+++ b/app/src/main/java/com/owncloud/android/ui/dialog/AccountRemovalConfirmationDialog.java
@@ -28,6 +28,9 @@
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.nextcloud.client.account.User;
import com.nextcloud.client.di.Injectable;
+import com.nextcloud.client.preferences.AppPreferences;
+import com.nmc.android.marketTracking.AdjustSdkUtils;
+import com.nmc.android.marketTracking.TealiumSdkUtils;
import com.nextcloud.client.jobs.BackgroundJobManager;
import com.owncloud.android.R;
import com.owncloud.android.utils.theme.ViewThemeUtils;
@@ -44,6 +47,7 @@ public class AccountRemovalConfirmationDialog extends DialogFragment implements
@Inject BackgroundJobManager backgroundJobManager;
@Inject ViewThemeUtils viewThemeUtils;
+ @Inject AppPreferences appPreferences;
private User user;
public static AccountRemovalConfirmationDialog newInstance(User user) {
@@ -80,8 +84,13 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
.setMessage(getResources().getString(R.string.delete_account_warning, user.getAccountName()))
.setIcon(R.drawable.ic_warning)
.setPositiveButton(R.string.common_ok,
- (dialogInterface, i) -> backgroundJobManager.startAccountRemovalJob(user.getAccountName(),
- false))
+ (dialogInterface, i) -> {
+ // track adjust and tealium events on logout confirmed
+ AdjustSdkUtils.trackEvent(AdjustSdkUtils.EVENT_TOKEN_SETTINGS_LOGOUT, appPreferences);
+ TealiumSdkUtils.trackEvent(TealiumSdkUtils.EVENT_SETTINGS_LOGOUT, appPreferences);
+
+ backgroundJobManager.startAccountRemovalJob(user.getAccountName(), false);
+ })
.setNeutralButton(R.string.common_cancel, null);
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(requireActivity(), builder);
diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
index f4034efa1f23..f45e304bbd76 100644
--- a/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
+++ b/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
@@ -50,6 +50,7 @@
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
import com.nextcloud.utils.MenuUtils;
+import com.nmc.android.marketTracking.TealiumSdkUtils;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.databinding.FileDetailsFragmentBinding;
@@ -358,6 +359,8 @@ public void onStart() {
super.onStart();
listenForTransferProgress();
EventBus.getDefault().register(this);
+ //track screen view when fragment is visible
+ TealiumSdkUtils.trackView(TealiumSdkUtils.SCREEN_VIEW_SHARING, preferences);
}
@Override
diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java
index cde91289f708..ac39d3814cab 100644
--- a/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java
+++ b/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java
@@ -56,6 +56,9 @@
import com.owncloud.android.ui.adapter.ShareeListAdapter;
import com.owncloud.android.ui.adapter.ShareeListAdapterListener;
import com.owncloud.android.ui.asynctasks.RetrieveHoverCardAsyncTask;
+import com.nextcloud.client.preferences.AppPreferences;
+import com.nmc.android.marketTracking.AdjustSdkUtils;
+import com.nmc.android.marketTracking.TealiumSdkUtils;
import com.owncloud.android.ui.dialog.SharePasswordDialogFragment;
import com.owncloud.android.ui.fragment.util.FileDetailSharingFragmentHelper;
import com.owncloud.android.ui.helpers.FileOperationsHelper;
@@ -98,6 +101,7 @@ public class FileDetailSharingFragment extends Fragment implements ShareeListAda
@Inject UserAccountManager accountManager;
@Inject ClientFactory clientFactory;
@Inject ViewThemeUtils viewThemeUtils;
+ @Inject AppPreferences appPreferences;
public static FileDetailSharingFragment newInstance(OCFile file, User user) {
FileDetailSharingFragment fragment = new FileDetailSharingFragment();
@@ -280,6 +284,10 @@ public void createPublicShareLink() {
// create without password if not enforced by server or we don't know if enforced;
fileOperationsHelper.shareFileViaPublicShare(file, null);
}
+
+ //track event on creating share link
+ AdjustSdkUtils.trackEvent(AdjustSdkUtils.EVENT_TOKEN_CREATE_SHARING_LINK, appPreferences);
+ TealiumSdkUtils.trackEvent(TealiumSdkUtils.EVENT_CREATE_SHARING_LINK, appPreferences);
}
@Override
diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java
index 95701987ab50..323244f04046 100644
--- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java
+++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java
@@ -29,7 +29,9 @@
import com.nextcloud.client.device.DeviceInfo;
import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.documentscan.AppScanOptionalFeature;
+import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.nextcloud.utils.EditorUtils;
+import com.nmc.android.marketTracking.TealiumSdkUtils;
import com.owncloud.android.R;
import com.owncloud.android.databinding.FileListActionsBottomSheetCreatorBinding;
import com.owncloud.android.databinding.FileListActionsBottomSheetFragmentBinding;
@@ -170,6 +172,12 @@ protected void onCreate(Bundle savedInstanceState) {
}
setupClickListener();
+
+ //track screen view when fragment is visible
+ TealiumSdkUtils.trackView(TealiumSdkUtils.SCREEN_VIEW_FAB_PLUS,
+ //Need to create direct instance of AppPreferences as Injection doesn't work in Dialogs
+ //If we take AppPreferences as parameter in constructor it will affect the other NMC PRs test cases
+ AppPreferencesImpl.fromContext(fileActivity));
}
private void setupClickListener() {
diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
index 3cb523a6e4b3..251ee4051d19 100644
--- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
+++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
@@ -64,7 +64,11 @@
import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
import com.nextcloud.utils.EditorUtils;
import com.nextcloud.utils.ShortcutUtil;
+import com.nmc.android.marketTracking.TrackingScanInterface;
import com.nextcloud.utils.view.FastScrollUtils;
+import com.nmc.android.marketTracking.AdjustSdkUtils;
+import com.nmc.android.marketTracking.TrackingScanInterfaceImpl;
+import com.nmc.android.marketTracking.TealiumSdkUtils;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
@@ -232,6 +236,13 @@ public class OCFileListFragment extends ExtendedListFragment implements
@Inject DeviceInfo deviceInfo;
+ /**
+ * Things to note about both the branches. 1. nmc/1867-scanbot branch: --> interface won't be initialised -->
+ * calling of interface method will be done here 2. nmc/1925-market_tracking --> interface will be initialised -->
+ * calling of interface method won't be done here
+ */
+ private TrackingScanInterface trackingScanInterface;
+
protected enum MenuItemAddRemove {
DO_NOTHING,
REMOVE_SORT,
@@ -256,6 +267,9 @@ public void onCreate(Bundle savedInstanceState) {
}
searchFragment = currentSearchType != null && isSearchEventSet(searchEvent);
+
+ //NMC customization will be initialised in nmc/1925-market_tracking
+ trackingScanInterface = new TrackingScanInterfaceImpl();
}
@Override
@@ -517,6 +531,10 @@ public void uploadFromApp() {
Intent.createChooser(action, getString(R.string.upload_chooser_title)),
FileDisplayActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS
);
+
+ //track event photo/video/any upload button click
+ AdjustSdkUtils.trackEvent(AdjustSdkUtils.EVENT_TOKEN_FAB_BOTTOM_PHOTO_VIDEO_UPLOAD, preferences);
+ TealiumSdkUtils.trackEvent(TealiumSdkUtils.EVENT_FAB_BOTTOM_PHOTO_VIDEO_UPLOAD, preferences);
}
@Override
@@ -529,6 +547,10 @@ public void directCameraUpload() {
} else {
DisplayUtils.showSnackMessage(getView(), getString(R.string.error_starting_direct_camera_upload));
}
+
+ //track event for camera upload button click
+ AdjustSdkUtils.trackEvent(AdjustSdkUtils.EVENT_TOKEN_FAB_BOTTOM_CAMERA_UPLOAD, preferences);
+ TealiumSdkUtils.trackEvent(TealiumSdkUtils.EVENT_FAB_BOTTOM_CAMERA_UPLOAD, preferences);
}
@Override
@@ -559,6 +581,10 @@ public void uploadFiles() {
FileDisplayActivity.REQUEST_CODE__SELECT_FILES_FROM_FILE_SYSTEM,
getCurrentFile().isEncrypted()
);
+
+ //track event for uploading files button click
+ AdjustSdkUtils.trackEvent(AdjustSdkUtils.EVENT_TOKEN_FAB_BOTTOM_FILE_UPLOAD, preferences);
+ TealiumSdkUtils.trackEvent(TealiumSdkUtils.EVENT_FAB_BOTTOM_FILE_UPLOAD, preferences);
}
@Override
@@ -587,6 +613,14 @@ public void onShareIconClick(OCFile file) {
mContainerActivity.getFileOperationsHelper().sendShareFile(file);
});
}
+
+ //track event on click of Share button
+ trackSharingClickEvent();
+ }
+
+ private void trackSharingClickEvent() {
+ AdjustSdkUtils.trackEvent(AdjustSdkUtils.EVENT_TOKEN_FILE_BROWSER_SHARING, preferences);
+ TealiumSdkUtils.trackEvent(TealiumSdkUtils.EVENT_FILE_BROWSER_SHARING, preferences);
}
@Override
@@ -1154,6 +1188,8 @@ public boolean onFileActionChosen(@IdRes final int itemId, Set checkedFi
if (itemId == R.id.action_send_share_file) {
mContainerActivity.getFileOperationsHelper().sendShareFile(singleFile);
+ //track event on click of Share button
+ trackSharingClickEvent();
return true;
} else if (itemId == R.id.action_open_file_with) {
mContainerActivity.getFileOperationsHelper().openFile(singleFile);
@@ -1182,6 +1218,9 @@ public boolean onFileActionChosen(@IdRes final int itemId, Set checkedFi
mContainerActivity.showDetails(singleFile);
mContainerActivity.showSortListGroup(false);
+
+ //track event on click of Share button
+ trackSharingClickEvent();
return true;
} else if (itemId == R.id.action_set_as_wallpaper) {
mContainerActivity.getFileOperationsHelper().setPictureAs(singleFile, getView());
diff --git a/gradle.properties b/gradle.properties
index 85bc2ba7da37..add468064c4c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -8,6 +8,8 @@ android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
#android.debug.obsoleteApi=true
+ADJUST_APP_TOKEN="54qd7rraqav4"
+MOENGAGE_APP_ID="XGJ4VU4OZ7HFU7EV5WTATM9K"
# Minimum max heap space to get reliable builds
org.gradle.jvmargs=-Xmx1g