diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c89f2310843b..5587a25f3ee2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -79,6 +79,7 @@ val configProps = Properties().apply { if (file.exists()) load(FileInputStream(file)) } +val adjustAppToken = project.properties["ADJUST_APP_TOKEN"] val ncTestServerUsername = configProps["NC_TEST_SERVER_USERNAME"] val ncTestServerPassword = configProps["NC_TEST_SERVER_PASSWORD"] val ncTestServerBaseUrl = configProps["NC_TEST_SERVER_BASEURL"] @@ -100,7 +101,8 @@ android { buildConfigField("boolean", "CI", ciBuild.toString()) buildConfigField("boolean", "RUNTIME_PERF_ANALYSIS", perfAnalysis.toString()) - + // NMC Customization: adjust token + buildConfigField("String", "ADJUST_APP_TOKEN", adjustAppToken.toString()) javaCompileOptions.annotationProcessorOptions { arguments += mapOf("room.schemaLocation" to "$projectDir/schemas") } @@ -502,6 +504,14 @@ dependencies { implementation(libs.kotlin.stdlib) // endregion + // NMC region + // Adjust SDK --> https://github.com/adjust/android_sdk + implementation(libs.adjust.android) + implementation(libs.installreferrer) + // tealium sdk + implementation(libs.tealium.library) + // endregion + // region Stateless implementation(libs.stateless4j) // endregion @@ -520,4 +530,7 @@ dependencies { // kotlinx.serialization implementation(libs.kotlinx.serialization.json) + + // NMC: dependency required to capture Advertising ID for Adjust & MoEngage SDK + implementation(libs.play.services.ads.identifier) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 940739adb944..c4b8cca4b584 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -653,6 +653,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); + } + public static void setAppTheme(DarkMode mode) { switch (mode) { case LIGHT -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); 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 14eb2eec5d38..acbb07b1f3cf 100644 --- a/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java @@ -66,6 +66,8 @@ import com.nextcloud.utils.extensions.BundleExtensionsKt; import com.nextcloud.utils.mdm.MDMConfig; import com.owncloud.android.BuildConfig; +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; @@ -1413,6 +1415,10 @@ public void onAuthenticatorTaskCallback(RemoteOperationResult result) } private void endSuccess() { + // NMC: track successful login event + AdjustSdkUtils.trackEvent(AdjustSdkUtils.EVENT_TOKEN_SUCCESSFUL_LOGIN, preferences); + TealiumSdkUtils.trackEvent(TealiumSdkUtils.EVENT_SUCCESSFUL_LOGIN, preferences); + if (!onlyAdd) { if (MDMConfig.INSTANCE.enforceProtection(this) && Objects.equals(preferences.getLockPreference(), SettingsActivity.LOCK_NONE)) { Intent i = new Intent(this, SettingsActivity.class); @@ -1756,4 +1762,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.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index 30b20ac632da..8f3a9d8a0bcf 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -86,6 +86,7 @@ import com.nextcloud.utils.extensions.navigateToAllFiles import com.nextcloud.utils.extensions.observeWorker import com.nextcloud.utils.fileNameValidator.FileNameValidator.checkFolderPath import com.nextcloud.utils.view.FastScrollUtils +import com.nmc.android.marketTracking.TealiumSdkUtils import com.owncloud.android.MainApp import com.owncloud.android.R import com.owncloud.android.databinding.FilesBinding @@ -2873,6 +2874,9 @@ class FileDisplayActivity : setNewLastDisplayedAccountName(existingAccountName) EventBus.getDefault().post(TokenPushEvent()) checkForNewDevVersionNecessary(applicationContext) + + // NMC: track screen view when activity is visible + TealiumSdkUtils.trackView(TealiumSdkUtils.SCREEN_VIEW_FILE_BROWSER, preferences) } private fun setNewLastDisplayedAccountName(accountName: String) { 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 ffdbfd72ae9a..3fad9f356049 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 @@ -54,6 +54,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.nextcloud.utils.extensions.ContextExtensionsKt; @@ -1176,6 +1177,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 96a853af2a40..fa64f9725bae 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 @@ -39,6 +39,8 @@ import com.nextcloud.client.preferences.SubFolderRule import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.isDialogFragmentReady import com.nextcloud.utils.extensions.setVisibleIf +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 @@ -578,6 +580,9 @@ class SyncedFoldersActivity : backgroundJobManager.startAutoUploadImmediately(syncedFolderDisplayItem, overridePowerSaving = false) showBatteryOptimizationInfo() } + + //track event when user enable/disable auto upload on/off + trackAutoUploadEvent(syncedFolderDisplayItem.isEnabled) } override fun onSyncFolderSettingsClick(section: Int, syncedFolderDisplayItem: SyncedFolderDisplayItem?) { @@ -712,6 +717,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) } override fun showSubFolderWarningDialog() { diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/AccountRemovalDialog.kt b/app/src/main/java/com/owncloud/android/ui/dialog/AccountRemovalDialog.kt index 3516bf4564ce..f07de12e475f 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/AccountRemovalDialog.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/AccountRemovalDialog.kt @@ -9,30 +9,23 @@ package com.owncloud.android.ui.dialog import android.app.Dialog -import android.graphics.drawable.Drawable +import android.content.DialogInterface import android.os.Bundle -import android.view.View -import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment -import com.google.android.material.button.MaterialButton import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.client.account.User -import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.di.Injectable import com.nextcloud.client.jobs.BackgroundJobManager +import com.nextcloud.client.preferences.AppPreferences +import com.nmc.android.marketTracking.AdjustSdkUtils +import com.nmc.android.marketTracking.TealiumSdkUtils import com.nextcloud.utils.extensions.getParcelableArgument import com.owncloud.android.R -import com.owncloud.android.databinding.AccountRemovalDialogBinding -import com.owncloud.android.datamodel.FileDataStorageManager -import com.owncloud.android.utils.DisplayUtils -import com.owncloud.android.utils.DisplayUtils.AvatarGenerationListener import com.owncloud.android.utils.theme.ViewThemeUtils import javax.inject.Inject -class AccountRemovalDialog : - DialogFragment(), - AvatarGenerationListener, - Injectable { +// NMC Customization: We don't need two option for logout. On logout directly logout the user locally from the app +class AccountRemovalDialog : DialogFragment(), Injectable { @Inject lateinit var backgroundJobManager: BackgroundJobManager @@ -40,135 +33,37 @@ class AccountRemovalDialog : @Inject lateinit var viewThemeUtils: ViewThemeUtils + @Inject + lateinit var appPreferences: AppPreferences + private var user: User? = null - private lateinit var alertDialog: AlertDialog - private var _binding: AccountRemovalDialogBinding? = null - val binding get() = _binding!! override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) user = requireArguments().getParcelableArgument(KEY_USER, User::class.java) } - override fun onStart() { - super.onStart() - - // disable positive button and apply theming - alertDialog = dialog as AlertDialog - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false - - viewThemeUtils.platform.themeRadioButton(binding.radioLocalRemove) - viewThemeUtils.platform.themeRadioButton(binding.radioRequestDeletion) - viewThemeUtils.material.colorMaterialButtonPrimaryTonal( - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as MaterialButton - ) - viewThemeUtils.material.colorMaterialButtonPrimaryBorderless( - alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as MaterialButton - ) - - binding.userName.text = UserAccountManager.getDisplayName(user) - binding.account.text = user?.let { DisplayUtils.convertIdn(it.accountName, false) } - } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - _binding = AccountRemovalDialogBinding.inflate(layoutInflater) - - // start avatar generation - setAvatar() - - // hide second option when plug-in isn't installed - if (hasDropAccount()) { - binding.requestDeletion.visibility = View.VISIBLE - } - - val builder = - MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.delete_account) - .setView(binding.root) - .setNegativeButton(R.string.common_cancel) { _, _ -> } - .setPositiveButton(R.string.delete_account) { _, _ -> removeAccount() } - - // allow selection by clicking on list element - binding.localRemove.setOnClickListener { - binding.radioLocalRemove.performClick() - } - binding.requestDeletion.setOnClickListener { - binding.radioRequestDeletion.performClick() - } - - // set listeners for custom radio button list - binding.radioLocalRemove.setOnClickListener { - binding.radioRequestDeletion.isChecked = false - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).apply { - text = getText(R.string.delete_account) - isEnabled = true - } - } - binding.radioRequestDeletion.setOnClickListener { - binding.radioLocalRemove.isChecked = false - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).apply { - text = getString(R.string.request_account_deletion_button) - isEnabled = true + val builder = MaterialAlertDialogBuilder(requireActivity()) + .setTitle(R.string.delete_account) + .setMessage(resources.getString(R.string.delete_account_warning, user!!.accountName)) + .setIcon(R.drawable.ic_warning) + .setPositiveButton(R.string.common_ok) { _: DialogInterface?, _: Int -> + // 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!!.accountName, + false + ) } - } - - viewThemeUtils.dialog.colorMaterialAlertDialogBackground(requireActivity(), builder) + .setNegativeButton(R.string.common_cancel, null) return builder.create() } - /** - * Get value of `drop-account` capability. - */ - private fun hasDropAccount(): Boolean { - val capability = FileDataStorageManager(user, context?.contentResolver).getCapability(user) - return capability.dropAccount.isTrue - } - - /** - * Start removal of account. Depending on which option is checked, either a browser will open to request deletion, - * or the local account will be removed immediately. - */ - private fun removeAccount() { - user?.let { user -> - if (binding.radioRequestDeletion.isChecked) { - DisplayUtils.startLinkIntent(activity, user.server.uri.toString() + DROP_ACCOUNT_URI) - } else { - backgroundJobManager.startAccountRemovalJob(user.accountName, false) - } - } - } - - /** - * Start avatar generation. - */ - private fun setAvatar() { - try { - val imageView = binding.userIcon - imageView.tag = user!!.accountName - DisplayUtils.setAvatar( - user!!, - this, - resources.getDimension(R.dimen.list_item_avatar_icon_radius), - resources, - imageView, - context - ) - } catch (_: Exception) { - } - } - - override fun avatarGenerated(avatarDrawable: Drawable?, callContext: Any?) { - avatarDrawable?.let { - binding.userIcon.setImageDrawable(it) - } - } - - override fun shouldCallGeneratedCallback(tag: String?, callContext: Any?): Boolean = binding.userIcon.tag == tag - companion object { private const val KEY_USER = "USER" - private const val DROP_ACCOUNT_URI = "/settings/user/drop_account" @JvmStatic fun newInstance(user: User) = AccountRemovalDialog().apply { 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 e1990f7b652a..a7c5a5939cc4 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 @@ -40,6 +40,7 @@ import com.nextcloud.utils.extensions.BundleExtensionsKt; import com.nextcloud.utils.extensions.FileExtensionsKt; import com.nextcloud.utils.mdm.MDMConfig; +import com.nmc.android.marketTracking.TealiumSdkUtils; import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.databinding.FileDetailsFragmentBinding; @@ -398,6 +399,8 @@ public void onStart() { listenForTransferProgress(); EventBus.getDefault().register(this); EventBusFactory.INSTANCE.getDownloadProgressEventBus().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 969b29c8d349..fbc881a3337d 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 @@ -62,6 +62,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.share.RemoteShareRepository; import com.owncloud.android.ui.fragment.share.ShareRepository; @@ -116,6 +119,7 @@ public class FileDetailSharingFragment extends Fragment implements ShareeListAda @Inject ClientFactory clientFactory; @Inject ViewThemeUtils viewThemeUtils; @Inject UsersAndGroupsSearchConfig searchConfig; + @Inject AppPreferences appPreferences; public static FileDetailSharingFragment newInstance(OCFile file, User user) { FileDetailSharingFragment fragment = new FileDetailSharingFragment(); @@ -415,6 +419,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.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.kt index d67689722a45..9f61a52fc675 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.kt @@ -18,8 +18,10 @@ import com.nextcloud.client.device.DeviceInfo import com.nextcloud.client.di.Injectable import com.nextcloud.client.documentscan.AppScanOptionalFeature import com.nextcloud.utils.BuildHelper.isFlavourGPlay +import com.nextcloud.client.preferences.AppPreferencesImpl import com.nextcloud.utils.EditorUtils import com.owncloud.android.MainApp +import com.nmc.android.marketTracking.TealiumSdkUtils import com.owncloud.android.R import com.owncloud.android.databinding.FileListActionsBottomSheetCreatorBinding import com.owncloud.android.databinding.FileListActionsBottomSheetFragmentBinding @@ -84,6 +86,14 @@ class OCFileListBottomSheetDialog( binding.uploadContentFromOtherApps.text = context.getString(R.string.upload_files) } } + + // 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 fun applyBranding() { 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 25a1d1a0b192..13478b41226f 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 @@ -60,7 +60,11 @@ import com.nextcloud.utils.extensions.OCFileExtensionsKt; import com.nextcloud.utils.extensions.ViewExtensionsKt; import com.nextcloud.utils.fileNameValidator.FileNameValidator; +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, @@ -258,6 +269,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 @@ -545,6 +559,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 @@ -562,6 +580,10 @@ public void directCameraUpload() { } showDirectCameraUploadAlertDialog(fileDisplayActivity); + + // NMC: 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); } private void showDirectCameraUploadAlertDialog(FileDisplayActivity fileDisplayActivity) { @@ -615,6 +637,10 @@ public void uploadFiles() { boolean isWithinEncryptedFolder = file.isEncrypted(); UploadFilesActivity.startUploadActivityForResult(fileActivity, user.get(), FileDisplayActivity.REQUEST_CODE__SELECT_FILES_FROM_FILE_SYSTEM, isWithinEncryptedFolder); + + // 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 @@ -639,6 +665,14 @@ public void onShareIconClick(OCFile file) { } else { throttler.run("shareIconClick", () -> 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 @@ -1364,6 +1398,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); @@ -1394,6 +1430,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/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 63e97d1a9c78..e2a6f1ee50b2 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -243,8 +243,9 @@ Tägliche Sicherung Zu sichernde Daten Zugangsdaten falsch - Konto entfernen + Benutzer abmelden Einträge löschen + Benutzer %s auf diesem Gerät abmelden und lokale Daten löschen? Link löschen Auswahl aufheben Ziel-Dateiname diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a48e76517e0a..40e116092d00 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -242,7 +242,8 @@ Request account deletion Request deletion Request permanent deletion of account by service provider - Remove account + Logout user + Log out user %s on this device and delete local data? Avatar Active user Upload from… diff --git a/gradle.properties b/gradle.properties index 50cc48359122..b3150edffd23 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ NC_TEST_SERVER_PASSWORD=test android.useAndroidX=true android.nonTransitiveRClass=true #android.debug.obsoleteApi=true - +ADJUST_APP_TOKEN="54qd7rraqav4" # JVM arguments to optimize heap usage, enable heap dump on out-of-memory errors, and set the file encoding org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a24bcb59ab0d..8cf3df8d17cd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -53,6 +53,9 @@ kotlinxSerializationJson = "1.9.0" ksp = "2.3.3" leakcanary = "2.14" legacySupportV4Version = "1.0.0" +adjustAndroidVersion = "5.1.0" +installreferrerVersion = "2.2" +tealiumlibraryVersion = "5.8.0" libraryVersion = "1.3.0" lifecycleViewmodelKtxVersion = "2.10.0" loaderviewlibraryVersion = "3.0.0" @@ -73,6 +76,7 @@ playServicesBaseVersion = "18.9.0" prismVersion = "2.0.0" qrcodescannerVersion = "0.1.2.4" reviewKtxVersion = "2.0.2" +playServicesAdsIdentifierVersion = "18.0.1" roomVersion = "2.8.4" screengrabVersion = "2.1.1" sectionedRecyclerviewVersion = "0.6.1" @@ -137,6 +141,7 @@ flexbox = { module = "com.google.android.flexbox:flexbox", version.ref = "flexbo gson = { module = "com.google.code.gson:gson", version.ref = "gsonVersion" } html = { module = "io.noties.markwon:html", version.ref = "markwonVersion" } ical4j = { module = "org.mnode.ical4j:ical4j", version.ref = "ical4jVersion" } +play-services-ads-identifier = { module = "com.google.android.gms:play-services-ads-identifier", version.ref = "playServicesAdsIdentifierVersion" } jackrabbit-webdav = { module = "org.apache.jackrabbit:jackrabbit-webdav", version.ref = "jackrabbitWebdavVersion" } json = { module = "org.json:json", version.ref = "jsonVersion" } juniversalchardet = { module = "com.github.albfernandez:juniversalchardet", version.ref = "juniversalchardetVersion" } @@ -172,6 +177,11 @@ lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", v lifecycle-service = { module = "androidx.lifecycle:lifecycle-service", version.ref = "lifecycleViewmodelKtxVersion" } lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtxVersion" } +# NMC Marketing +adjust-android = { module = "com.adjust.sdk:adjust-android", version.ref = "adjustAndroidVersion" } +installreferrer = { module = "com.android.installreferrer:installreferrer", version.ref = "installreferrerVersion" } +tealium-library = { module = "com.tealium:library", version.ref = "tealiumlibraryVersion" } + # ksp ksp = { module = "com.github.bumptech.glide:ksp", version.ref = "glide" } diff --git a/settings.gradle.kts b/settings.gradle.kts index c0ebf04488ac..4235ffc8bfdf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -36,6 +36,8 @@ dependencyResolutionManagement { } } mavenCentral() + // NMC Customization: tealium + maven("https://maven.tealiumiq.com/android/releases/") maven("https://jitpack.io") } }