Skip to content

Commit 7afaea2

Browse files
Merge pull request #14401 from nextcloud/backport/14247/stable-3.30
[stable-3.30] request media_location
2 parents 3f3a90f + 50e910c commit 7afaea2

File tree

12 files changed

+168
-9
lines changed

12 files changed

+168
-9
lines changed

app/src/gplay/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
tools:node="remove"
1919
tools:ignore="ScopedStorage" />
2020

21+
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
22+
2123
<application
2224
android:name=".MainApp"
2325
android:icon="@mipmap/ic_launcher"

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
<uses-permission
4949
android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
5050
android:maxSdkVersion="25" />
51+
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
5152
<!--
5253
Apps that target Android 9 (API level 28) or higher and use foreground services
5354
must request the FOREGROUND_SERVICE permission

app/src/main/java/com/nextcloud/client/jobs/MediaFoldersDetectionWork.kt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import com.nextcloud.client.account.UserAccountManager
3232
import com.nextcloud.client.core.Clock
3333
import com.nextcloud.client.preferences.AppPreferences
3434
import com.nextcloud.client.preferences.AppPreferencesImpl
35+
import com.nextcloud.utils.BuildHelper
3536
import com.owncloud.android.MainApp
3637
import com.owncloud.android.R
3738
import com.owncloud.android.datamodel.ArbitraryDataProvider
@@ -41,6 +42,7 @@ import com.owncloud.android.datamodel.MediaFoldersModel
4142
import com.owncloud.android.datamodel.MediaProvider
4243
import com.owncloud.android.datamodel.SyncedFolderProvider
4344
import com.owncloud.android.lib.common.utils.Log_OC
45+
import com.owncloud.android.ui.activity.FileDisplayActivity
4446
import com.owncloud.android.ui.activity.ManageAccountsActivity.PENDING_FOR_REMOVAL
4547
import com.owncloud.android.ui.activity.SyncedFoldersActivity
4648
import com.owncloud.android.ui.notifications.NotificationUtils
@@ -190,9 +192,51 @@ class MediaFoldersDetectionWork constructor(
190192
gson.toJson(mediaFoldersModel)
191193
)
192194
}
195+
196+
// only send notification when synced folder is setup, gplay flavor and not branded client
197+
@Suppress("ComplexMethod")
198+
if (syncedFolderProvider.syncedFolders.isNotEmpty() &&
199+
BuildHelper.isFlavourGPlay() &&
200+
!preferences.isAutoUploadGPlayNotificationShown &&
201+
!MainApp.isClientBranded()
202+
) {
203+
sendAutoUploadNotification()
204+
}
205+
193206
return Result.success()
194207
}
195208

209+
private fun sendAutoUploadNotification() {
210+
val notificationId = randomIdGenerator.nextInt()
211+
val intent = Intent().apply {
212+
setClassName(context, FileDisplayActivity::class.java.name)
213+
setAction(FileDisplayActivity.AUTO_UPLOAD_NOTIFICATION)
214+
}
215+
val pendingIntent = PendingIntent.getActivity(
216+
context,
217+
0,
218+
intent,
219+
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
220+
)
221+
222+
val notificationBuilder = NotificationCompat.Builder(
223+
context,
224+
NotificationUtils.NOTIFICATION_CHANNEL_GENERAL
225+
)
226+
.setSmallIcon(R.drawable.notification_icon)
227+
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.notification_icon))
228+
.setContentTitle(context.getString(R.string.re_enable_auto_upload))
229+
.setContentText(context.getString(R.string.click_to_learn_how_to_re_enable_auto_uploads))
230+
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
231+
.setAutoCancel(true)
232+
.setContentIntent(pendingIntent)
233+
234+
viewThemeUtils.androidx.themeNotificationCompatBuilder(context, notificationBuilder)
235+
236+
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
237+
notificationManager.notify(notificationId, notificationBuilder.build())
238+
}
239+
196240
@Suppress("LongMethod")
197241
private fun sendNotification(contentTitle: String, subtitle: String, user: User, path: String, type: Int) {
198242
val notificationId = randomIdGenerator.nextInt()

app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,4 +403,10 @@ default void onDarkThemeModeChanged(DarkMode mode) {
403403

404404
boolean isAutoUploadGPlayWarningShown();
405405
void setAutoUploadGPlayWarningShown(boolean value);
406+
407+
boolean isAutoUploadGPlayWarning2Shown();
408+
void setAutoUploadGPlayWarning2Shown(boolean value);
409+
410+
boolean isAutoUploadGPlayNotificationShown();
411+
void setAutoUploadGPlayNotificationShown(boolean value);
406412
}

app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ public final class AppPreferencesImpl implements AppPreferences {
108108
private static final String PREF__STOP_DOWNLOAD_JOBS_ON_START = "stop_download_jobs_on_start";
109109

110110
private static final String PREF__AUTO_UPLOAD_GPLAY_WARNING_SHOWN = "auto_upload_gplay_warning_shown";
111+
private static final String PREF__AUTO_UPLOAD_GPLAY_WARNING2_SHOWN = "auto_upload_gplay_warning2_shown";
112+
private static final String PREF__AUTO_UPLOAD_GPLAY_NOTIFICATION_SHOWN = "auto_upload_gplay_notification_shown";
111113

112114
private static final String LOG_ENTRY = "log_entry";
113115

@@ -836,4 +838,24 @@ public boolean isAutoUploadGPlayWarningShown() {
836838
public void setAutoUploadGPlayWarningShown(boolean value) {
837839
preferences.edit().putBoolean(PREF__AUTO_UPLOAD_GPLAY_WARNING_SHOWN, value).apply();
838840
}
841+
842+
@Override
843+
public boolean isAutoUploadGPlayWarning2Shown() {
844+
return preferences.getBoolean(PREF__AUTO_UPLOAD_GPLAY_WARNING2_SHOWN, false);
845+
}
846+
847+
@Override
848+
public void setAutoUploadGPlayWarning2Shown(boolean value) {
849+
preferences.edit().putBoolean(PREF__AUTO_UPLOAD_GPLAY_WARNING2_SHOWN, value).apply();
850+
}
851+
852+
@Override
853+
public boolean isAutoUploadGPlayNotificationShown() {
854+
return preferences.getBoolean(PREF__AUTO_UPLOAD_GPLAY_NOTIFICATION_SHOWN, false);
855+
}
856+
857+
@Override
858+
public void setAutoUploadGPlayNotificationShown(boolean value) {
859+
preferences.edit().putBoolean(PREF__AUTO_UPLOAD_GPLAY_NOTIFICATION_SHOWN, value).apply();
860+
}
839861
}

app/src/main/java/com/owncloud/android/MainApp.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,13 @@ private void setProxyForNonBrandedPlusClients() {
403403
Log_OC.d(TAG, "Error caught at setProxyForNonBrandedPlusClients: " + e);
404404
}
405405
}
406+
407+
public static boolean isClientBranded() {
408+
return getAppContext().getResources().getBoolean(R.bool.is_branded_client);
409+
}
406410

407411
public static boolean isClientBrandedPlus() {
408-
return (getAppContext().getResources().getBoolean(R.bool.is_branded_plus_client));
412+
return getAppContext().getResources().getBoolean(R.bool.is_branded_plus_client);
409413
}
410414

411415
private final IntentFilter restrictionsFilter = new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);

app/src/main/java/com/owncloud/android/datamodel/OCFile.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import android.text.TextUtils;
2222

2323
import com.nextcloud.utils.BuildHelper;
24-
import com.owncloud.android.BuildConfig;
2524
import com.owncloud.android.R;
2625
import com.owncloud.android.lib.common.network.WebdavEntry;
2726
import com.owncloud.android.lib.common.network.WebdavUtils;
@@ -1085,7 +1084,7 @@ public void setInternalFolderSyncResult(String internalFolderSyncResult) {
10851084
}
10861085

10871086
public boolean isAPKorAAB() {
1088-
if (BuildHelper.GPLAY.equals(BuildConfig.FLAVOR)) {
1087+
if (BuildHelper.INSTANCE.isFlavourGPlay()) {
10891088
return getFileName().endsWith(".apk") || getFileName().endsWith(".aab");
10901089
} else {
10911090
return false;

app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@
7373
import com.nextcloud.utils.extensions.IntentExtensionsKt;
7474
import com.nextcloud.utils.fileNameValidator.FileNameValidator;
7575
import com.nextcloud.utils.view.FastScrollUtils;
76-
import com.owncloud.android.BuildConfig;
7776
import com.owncloud.android.MainApp;
7877
import com.owncloud.android.R;
7978
import com.owncloud.android.databinding.FilesBinding;
8079
import com.owncloud.android.datamodel.FileDataStorageManager;
80+
import com.owncloud.android.datamodel.MediaFolderType;
8181
import com.owncloud.android.datamodel.OCFile;
8282
import com.owncloud.android.datamodel.SyncedFolder;
8383
import com.owncloud.android.datamodel.SyncedFolderProvider;
@@ -176,6 +176,7 @@ public class FileDisplayActivity extends FileActivity
176176
public static final String RESTART = "RESTART";
177177
public static final String ALL_FILES = "ALL_FILES";
178178
public static final String LIST_GROUPFOLDERS = "LIST_GROUPFOLDERS";
179+
public static final String AUTO_UPLOAD_NOTIFICATION = "AUTO_UPLOAD_NOTIFICATION";
179180
public static final int SINGLE_USER_SIZE = 1;
180181
public static final String OPEN_FILE = "NC_OPEN_FILE";
181182

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

285286
checkStoragePath();
286-
checkAutoUploadOnGPlay();
287+
notifyGPlayPermissionChanges();
288+
showAutoUploadWarningForGPlayFlavour();
287289

288290
initSyncBroadcastReceiver();
289291
observeWorkerState();
290292
registerRefreshFolderEventReceiver();
291293
}
292294

293-
private void checkAutoUploadOnGPlay() {
294-
if (!BuildHelper.GPLAY.equals(BuildConfig.FLAVOR)) {
295+
private void notifyGPlayPermissionChanges() {
296+
if (!BuildHelper.INSTANCE.isFlavourGPlay() || MainApp.isClientBranded()) {
295297
return;
296298
}
297299

@@ -333,6 +335,41 @@ private void checkAutoUploadOnGPlay() {
333335
preferences.setAutoUploadGPlayWarningShown(true);
334336
}
335337

338+
private void showAutoUploadWarningForGPlayFlavour() {
339+
if (!BuildHelper.INSTANCE.isFlavourGPlay() || MainApp.isClientBranded()) {
340+
return;
341+
}
342+
343+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
344+
return;
345+
}
346+
347+
boolean showAutoUploadDialog = false;
348+
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
349+
if (syncedFolder.getType() == MediaFolderType.CUSTOM) {
350+
showAutoUploadDialog = true;
351+
break;
352+
}
353+
}
354+
355+
if (!preferences.isAutoUploadGPlayWarning2Shown()) {
356+
String title = showAutoUploadDialog ? getString(R.string.auto_upload_gplay) : getString(R.string.upload_gplay);
357+
String message = showAutoUploadDialog ? getString(R.string.auto_upload_gplay_desc2) : getString(R.string.upload_gplay_desc);
358+
359+
new MaterialAlertDialogBuilder(this, R.style.Theme_ownCloud_Dialog)
360+
.setTitle(title)
361+
.setMessage(message)
362+
.setNegativeButton(R.string.dialog_close, (dialog, which) -> {
363+
PermissionUtil.requestMediaLocationPermission(this);
364+
preferences.setAutoUploadGPlayWarning2Shown(true);
365+
dialog.dismiss();
366+
})
367+
.setIcon(R.drawable.nav_synced_folders)
368+
.create()
369+
.show();
370+
}
371+
}
372+
336373
@SuppressWarnings("unchecked")
337374
private void loadSavedInstanceState(Bundle savedInstanceState) {
338375
if (savedInstanceState != null) {
@@ -617,9 +654,24 @@ protected void onNewIntent(Intent intent) {
617654

618655
setLeftFragment(new GroupfolderListFragment());
619656
getSupportFragmentManager().executePendingTransactions();
657+
} else if (AUTO_UPLOAD_NOTIFICATION.equals(intent.getAction())) {
658+
handleAutoUploadNotification();
620659
}
621660
}
622661
}
662+
663+
private void handleAutoUploadNotification() {
664+
new MaterialAlertDialogBuilder(this, R.style.Theme_ownCloud_Dialog)
665+
.setTitle(R.string.re_enable_auto_upload)
666+
.setMessage(R.string.re_enable_auto_upload_desc)
667+
.setNegativeButton(R.string.dialog_close, (dialog, which) -> {
668+
dialog.dismiss();
669+
preferences.setAutoUploadGPlayNotificationShown(true);
670+
})
671+
.setIcon(R.drawable.nav_synced_folders)
672+
.create()
673+
.show();
674+
}
623675

624676
private void onOpenFileIntent(Intent intent) {
625677
String extra = intent.getStringExtra(EXTRA_FILE);

app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ public void registerFabListener() {
486486
// is not available in FolderPickerActivity
487487
viewThemeUtils.material.themeFAB(mFabMain);
488488
mFabMain.setOnClickListener(v -> {
489+
PermissionUtil.requestMediaLocationPermission(activity);
490+
489491
final OCFileListBottomSheetDialog dialog =
490492
new OCFileListBottomSheetDialog(activity,
491493
this,

app/src/main/java/com/owncloud/android/utils/PermissionUtil.kt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ object PermissionUtil {
3939
const val PERMISSIONS_READ_CALENDAR_AUTOMATIC = 6
4040
const val PERMISSIONS_WRITE_CALENDAR = 7
4141
const val PERMISSIONS_POST_NOTIFICATIONS = 8
42+
const val PERMISSIONS_MEDIA_LOCATION = 9
4243

4344
const val REQUEST_CODE_MANAGE_ALL_FILES = 19203
4445

@@ -151,7 +152,8 @@ object PermissionUtil {
151152
// use granular media permissions
152153
arrayOf(
153154
Manifest.permission.READ_MEDIA_IMAGES,
154-
Manifest.permission.READ_MEDIA_VIDEO
155+
Manifest.permission.READ_MEDIA_VIDEO,
156+
Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
155157
)
156158
} else {
157159
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
@@ -302,4 +304,23 @@ object PermissionUtil {
302304
}
303305
}
304306
}
307+
308+
/**
309+
* Request media location permission. Required on API level >= 34.
310+
* Does not have any effect on API level < 34.
311+
*
312+
* @param activity target activity
313+
*/
314+
@JvmStatic
315+
fun requestMediaLocationPermission(activity: Activity) {
316+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
317+
if (!checkSelfPermission(activity, Manifest.permission.ACCESS_MEDIA_LOCATION)) {
318+
ActivityCompat.requestPermissions(
319+
activity,
320+
arrayOf(Manifest.permission.ACCESS_MEDIA_LOCATION),
321+
PERMISSIONS_MEDIA_LOCATION
322+
)
323+
}
324+
}
325+
}
305326
}

0 commit comments

Comments
 (0)