Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/gplay/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
tools:node="remove"
tools:ignore="ScopedStorage" />

<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />

<application
android:name=".MainApp"
android:icon="@mipmap/ic_launcher"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<uses-permission
android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
android:maxSdkVersion="25" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<!--
Apps that target Android 9 (API level 28) or higher and use foreground services
must request the FOREGROUND_SERVICE permission
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.nextcloud.client.account.UserAccountManager
import com.nextcloud.client.core.Clock
import com.nextcloud.client.preferences.AppPreferences
import com.nextcloud.client.preferences.AppPreferencesImpl
import com.nextcloud.utils.BuildHelper
import com.owncloud.android.MainApp
import com.owncloud.android.R
import com.owncloud.android.datamodel.ArbitraryDataProvider
Expand All @@ -41,6 +42,7 @@ import com.owncloud.android.datamodel.MediaFoldersModel
import com.owncloud.android.datamodel.MediaProvider
import com.owncloud.android.datamodel.SyncedFolderProvider
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.ui.activity.ManageAccountsActivity.PENDING_FOR_REMOVAL
import com.owncloud.android.ui.activity.SyncedFoldersActivity
import com.owncloud.android.ui.notifications.NotificationUtils
Expand Down Expand Up @@ -190,9 +192,51 @@ class MediaFoldersDetectionWork constructor(
gson.toJson(mediaFoldersModel)
)
}

// only send notification when synced folder is setup, gplay flavor and not branded client
@Suppress("ComplexMethod")
if (syncedFolderProvider.syncedFolders.isNotEmpty() &&
BuildHelper.isFlavourGPlay() &&
!preferences.isAutoUploadGPlayNotificationShown &&
!MainApp.isClientBranded()
) {
sendAutoUploadNotification()
}

return Result.success()
}

private fun sendAutoUploadNotification() {
val notificationId = randomIdGenerator.nextInt()
val intent = Intent().apply {
setClassName(context, FileDisplayActivity::class.java.name)
setAction(FileDisplayActivity.AUTO_UPLOAD_NOTIFICATION)
}
val pendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)

val notificationBuilder = NotificationCompat.Builder(
context,
NotificationUtils.NOTIFICATION_CHANNEL_GENERAL
)
.setSmallIcon(R.drawable.notification_icon)
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.notification_icon))
.setContentTitle(context.getString(R.string.re_enable_auto_upload))
.setContentText(context.getString(R.string.click_to_learn_how_to_re_enable_auto_uploads))
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setAutoCancel(true)
.setContentIntent(pendingIntent)

viewThemeUtils.androidx.themeNotificationCompatBuilder(context, notificationBuilder)

val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(notificationId, notificationBuilder.build())
}

@Suppress("LongMethod")
private fun sendNotification(contentTitle: String, subtitle: String, user: User, path: String, type: Int) {
val notificationId = randomIdGenerator.nextInt()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,4 +403,10 @@ default void onDarkThemeModeChanged(DarkMode mode) {

boolean isAutoUploadGPlayWarningShown();
void setAutoUploadGPlayWarningShown(boolean value);

boolean isAutoUploadGPlayWarning2Shown();
void setAutoUploadGPlayWarning2Shown(boolean value);

boolean isAutoUploadGPlayNotificationShown();
void setAutoUploadGPlayNotificationShown(boolean value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public final class AppPreferencesImpl implements AppPreferences {
private static final String PREF__STOP_DOWNLOAD_JOBS_ON_START = "stop_download_jobs_on_start";

private static final String PREF__AUTO_UPLOAD_GPLAY_WARNING_SHOWN = "auto_upload_gplay_warning_shown";
private static final String PREF__AUTO_UPLOAD_GPLAY_WARNING2_SHOWN = "auto_upload_gplay_warning2_shown";
private static final String PREF__AUTO_UPLOAD_GPLAY_NOTIFICATION_SHOWN = "auto_upload_gplay_notification_shown";

private static final String LOG_ENTRY = "log_entry";

Expand Down Expand Up @@ -836,4 +838,24 @@ public boolean isAutoUploadGPlayWarningShown() {
public void setAutoUploadGPlayWarningShown(boolean value) {
preferences.edit().putBoolean(PREF__AUTO_UPLOAD_GPLAY_WARNING_SHOWN, value).apply();
}

@Override
public boolean isAutoUploadGPlayWarning2Shown() {
return preferences.getBoolean(PREF__AUTO_UPLOAD_GPLAY_WARNING2_SHOWN, false);
}

@Override
public void setAutoUploadGPlayWarning2Shown(boolean value) {
preferences.edit().putBoolean(PREF__AUTO_UPLOAD_GPLAY_WARNING2_SHOWN, value).apply();
}

@Override
public boolean isAutoUploadGPlayNotificationShown() {
return preferences.getBoolean(PREF__AUTO_UPLOAD_GPLAY_NOTIFICATION_SHOWN, false);
}

@Override
public void setAutoUploadGPlayNotificationShown(boolean value) {
preferences.edit().putBoolean(PREF__AUTO_UPLOAD_GPLAY_NOTIFICATION_SHOWN, value).apply();
}
}
6 changes: 5 additions & 1 deletion app/src/main/java/com/owncloud/android/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,13 @@ private void setProxyForNonBrandedPlusClients() {
Log_OC.d(TAG, "Error caught at setProxyForNonBrandedPlusClients: " + e);
}
}

public static boolean isClientBranded() {
return getAppContext().getResources().getBoolean(R.bool.is_branded_client);
}

public static boolean isClientBrandedPlus() {
return (getAppContext().getResources().getBoolean(R.bool.is_branded_plus_client));
return getAppContext().getResources().getBoolean(R.bool.is_branded_plus_client);
}

private final IntentFilter restrictionsFilter = new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/com/owncloud/android/datamodel/OCFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import android.text.TextUtils;

import com.nextcloud.utils.BuildHelper;
import com.owncloud.android.BuildConfig;
import com.owncloud.android.R;
import com.owncloud.android.lib.common.network.WebdavEntry;
import com.owncloud.android.lib.common.network.WebdavUtils;
Expand Down Expand Up @@ -1085,7 +1084,7 @@ public void setInternalFolderSyncResult(String internalFolderSyncResult) {
}

public boolean isAPKorAAB() {
if (BuildHelper.GPLAY.equals(BuildConfig.FLAVOR)) {
if (BuildHelper.INSTANCE.isFlavourGPlay()) {
return getFileName().endsWith(".apk") || getFileName().endsWith(".aab");
} else {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@
import com.nextcloud.utils.extensions.IntentExtensionsKt;
import com.nextcloud.utils.fileNameValidator.FileNameValidator;
import com.nextcloud.utils.view.FastScrollUtils;
import com.owncloud.android.BuildConfig;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.databinding.FilesBinding;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.MediaFolderType;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
Expand Down Expand Up @@ -176,6 +176,7 @@ public class FileDisplayActivity extends FileActivity
public static final String RESTART = "RESTART";
public static final String ALL_FILES = "ALL_FILES";
public static final String LIST_GROUPFOLDERS = "LIST_GROUPFOLDERS";
public static final String AUTO_UPLOAD_NOTIFICATION = "AUTO_UPLOAD_NOTIFICATION";
public static final int SINGLE_USER_SIZE = 1;
public static final String OPEN_FILE = "NC_OPEN_FILE";

Expand Down Expand Up @@ -283,15 +284,16 @@ protected void onCreate(Bundle savedInstanceState) {
mPlayerConnection = new PlayerServiceConnection(this);

checkStoragePath();
checkAutoUploadOnGPlay();
notifyGPlayPermissionChanges();
showAutoUploadWarningForGPlayFlavour();

initSyncBroadcastReceiver();
observeWorkerState();
registerRefreshFolderEventReceiver();
}

private void checkAutoUploadOnGPlay() {
if (!BuildHelper.GPLAY.equals(BuildConfig.FLAVOR)) {
private void notifyGPlayPermissionChanges() {
if (!BuildHelper.INSTANCE.isFlavourGPlay() || MainApp.isClientBranded()) {
return;
}

Expand Down Expand Up @@ -333,6 +335,41 @@ private void checkAutoUploadOnGPlay() {
preferences.setAutoUploadGPlayWarningShown(true);
}

private void showAutoUploadWarningForGPlayFlavour() {
if (!BuildHelper.INSTANCE.isFlavourGPlay() || MainApp.isClientBranded()) {
return;
}

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return;
}

boolean showAutoUploadDialog = false;
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.getType() == MediaFolderType.CUSTOM) {
showAutoUploadDialog = true;
break;
}
}

if (!preferences.isAutoUploadGPlayWarning2Shown()) {
String title = showAutoUploadDialog ? getString(R.string.auto_upload_gplay) : getString(R.string.upload_gplay);
String message = showAutoUploadDialog ? getString(R.string.auto_upload_gplay_desc2) : getString(R.string.upload_gplay_desc);

new MaterialAlertDialogBuilder(this, R.style.Theme_ownCloud_Dialog)
.setTitle(title)
.setMessage(message)
.setNegativeButton(R.string.dialog_close, (dialog, which) -> {
PermissionUtil.requestMediaLocationPermission(this);
preferences.setAutoUploadGPlayWarning2Shown(true);
dialog.dismiss();
})
.setIcon(R.drawable.nav_synced_folders)
.create()
.show();
}
}

@SuppressWarnings("unchecked")
private void loadSavedInstanceState(Bundle savedInstanceState) {
if (savedInstanceState != null) {
Expand Down Expand Up @@ -617,9 +654,24 @@ protected void onNewIntent(Intent intent) {

setLeftFragment(new GroupfolderListFragment());
getSupportFragmentManager().executePendingTransactions();
} else if (AUTO_UPLOAD_NOTIFICATION.equals(intent.getAction())) {
handleAutoUploadNotification();
}
}
}

private void handleAutoUploadNotification() {
new MaterialAlertDialogBuilder(this, R.style.Theme_ownCloud_Dialog)
.setTitle(R.string.re_enable_auto_upload)
.setMessage(R.string.re_enable_auto_upload_desc)
.setNegativeButton(R.string.dialog_close, (dialog, which) -> {
dialog.dismiss();
preferences.setAutoUploadGPlayNotificationShown(true);
})
.setIcon(R.drawable.nav_synced_folders)
.create()
.show();
}

private void onOpenFileIntent(Intent intent) {
String extra = intent.getStringExtra(EXTRA_FILE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,8 @@ public void registerFabListener() {
// is not available in FolderPickerActivity
viewThemeUtils.material.themeFAB(mFabMain);
mFabMain.setOnClickListener(v -> {
PermissionUtil.requestMediaLocationPermission(activity);

final OCFileListBottomSheetDialog dialog =
new OCFileListBottomSheetDialog(activity,
this,
Expand Down
23 changes: 22 additions & 1 deletion app/src/main/java/com/owncloud/android/utils/PermissionUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ object PermissionUtil {
const val PERMISSIONS_READ_CALENDAR_AUTOMATIC = 6
const val PERMISSIONS_WRITE_CALENDAR = 7
const val PERMISSIONS_POST_NOTIFICATIONS = 8
const val PERMISSIONS_MEDIA_LOCATION = 9

const val REQUEST_CODE_MANAGE_ALL_FILES = 19203

Expand Down Expand Up @@ -151,7 +152,8 @@ object PermissionUtil {
// use granular media permissions
arrayOf(
Manifest.permission.READ_MEDIA_IMAGES,
Manifest.permission.READ_MEDIA_VIDEO
Manifest.permission.READ_MEDIA_VIDEO,
Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
)
} else {
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
Expand Down Expand Up @@ -302,4 +304,23 @@ object PermissionUtil {
}
}
}

/**
* Request media location permission. Required on API level >= 34.
* Does not have any effect on API level < 34.
*
* @param activity target activity
*/
@JvmStatic
fun requestMediaLocationPermission(activity: Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (!checkSelfPermission(activity, Manifest.permission.ACCESS_MEDIA_LOCATION)) {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.ACCESS_MEDIA_LOCATION),
PERMISSIONS_MEDIA_LOCATION
)
}
}
}
}
6 changes: 6 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1255,4 +1255,10 @@
<string name="two_way_sync_activity_disable_all_button_title">Disable for all folders</string>
<string name="auto_upload_gplay">Auto upload behaviour changed</string>
<string name="auto_upload_gplay_desc">Due to new restrictions imposed by Google, the auto upload feature will no longer be able to automatically remove uploaded files.</string>
<string name="auto_upload_gplay_desc2">Due to new restrictions imposed by Google, we have been forced to remove an important permission. As a result, auto upload will only be able to upload image and video files.\nAdditionally, a new permission is required to access location information for uploaded images.\nMake sure that media access is set to \"Always allow all\".</string>
<string name="upload_gplay">Permission changes</string>
<string name="upload_gplay_desc">A new permission is required to access location information for uploaded images.\nMake sure that media access is set to \"Always allow all\".</string>
<string name="re_enable_auto_upload">Changes to auto upload</string>
<string name="re_enable_auto_upload_desc">Due to new restrictions imposed by Google, we have been forced to remove an important permission. We are currently working with Google to resolve this issue and restore full functionality.\n\nTo re-enable auto upload for new photos and videos:\nSelect \"Allow all\" in the following dialogue or the system settings.\nAllow Nextcloud to use location when prompted, as this allows us to store location when uploading images.\n\nAuto upload will no longer be able to upload any other files when using the Google Play version of the Nextcloud app.\n\nPlease check for any files that may not have been uploaded since December 2024.</string>
<string name="click_to_learn_how_to_re_enable_auto_uploads">Manual intervention required to re-enable auto-upload</string>
</resources>
2 changes: 1 addition & 1 deletion scripts/analysis/lint-results.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
DO NOT TOUCH; GENERATED BY DRONE
<span class="mdl-layout-title">Lint Report: 3 errors and 60 warnings</span>
<span class="mdl-layout-title">Lint Report: 3 errors and 59 warnings</span>