Skip to content

Commit 4302711

Browse files
Merge pull request #14879 from nextcloud/backport/14775/stable-3.31
[stable-3.31] Handle Downloaded File Open Intent
2 parents 438c95d + a467c9c commit 4302711

File tree

4 files changed

+88
-155
lines changed

4 files changed

+88
-155
lines changed

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

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.nextcloud.utils.BuildHelper;
2424
import com.owncloud.android.R;
2525
import com.owncloud.android.lib.common.network.WebdavEntry;
26-
import com.owncloud.android.lib.common.network.WebdavUtils;
2726
import com.owncloud.android.lib.common.utils.Log_OC;
2827
import com.owncloud.android.lib.resources.files.model.FileLockType;
2928
import com.owncloud.android.lib.resources.files.model.GeoLocation;
@@ -386,36 +385,19 @@ public Uri getStorageUri() {
386385
return localUri;
387386
}
388387

389-
390-
public Uri getLegacyExposedFileUri() {
391-
if (TextUtils.isEmpty(localPath)) {
392-
return null;
393-
}
394-
395-
if (exposedFileUri == null) {
396-
return Uri.parse(ContentResolver.SCHEME_FILE + "://" + WebdavUtils.encodePath(localPath));
397-
}
398-
399-
return exposedFileUri;
400-
401-
}
402-
/*
403-
Partly disabled because not all apps understand paths that we get via this method for now
404-
*/
405388
public Uri getExposedFileUri(Context context) {
406389
if (TextUtils.isEmpty(localPath)) {
407390
return null;
408391
}
392+
409393
if (exposedFileUri == null) {
410394
try {
411395
exposedFileUri = FileProvider.getUriForFile(
412396
context,
413397
context.getString(R.string.file_provider_authority),
414398
new File(localPath));
415399
} catch (IllegalArgumentException ex) {
416-
// Could not share file using FileProvider URI scheme.
417-
// Fall back to legacy URI parsing.
418-
getLegacyExposedFileUri();
400+
Log_OC.d(TAG, "Given File is outside the paths supported by the provider");
419401
}
420402
}
421403

app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import javax.inject.Inject
4848
/**
4949
* Wrapper activity which will be launched if keep-in-sync file will be modified by external application.
5050
*/
51+
@Suppress("Detekt.TooManyFunctions")
5152
class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener {
5253
@Inject
5354
lateinit var uploadsStorageManager: UploadsStorageManager

app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

Lines changed: 85 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@
8181
import java.nio.charset.StandardCharsets;
8282
import java.text.SimpleDateFormat;
8383
import java.util.ArrayList;
84-
import java.util.Arrays;
8584
import java.util.Collection;
8685
import java.util.Date;
8786
import java.util.List;
@@ -263,89 +262,94 @@ public boolean canOpenFile(OCFile file) {
263262
return !launchables.isEmpty();
264263
}
265264

265+
private void openRichDocumentFileWithoutAvailableApps(@NonNull OCFile file) {
266+
Account account = fileActivity.getAccount();
267+
OCCapability capability = fileActivity.getStorageManager().getCapability(account.name);
268+
final var richDocumentMimeTypeList = capability.getRichDocumentsMimeTypeList();
269+
270+
if (richDocumentMimeTypeList != null &&
271+
richDocumentMimeTypeList.contains(file.getMimeType()) &&
272+
capability.getRichDocumentsDirectEditing().isTrue()) {
273+
openFileAsRichDocument(file, fileActivity);
274+
} else {
275+
DisplayUtils.showSnackMessage(fileActivity, R.string.file_list_no_app_for_file_type);
276+
}
277+
}
278+
266279
public void openFile(OCFile file) {
267-
if (file != null) {
268-
final Intent openFileWithIntent = createOpenFileIntent(file);
280+
if (file == null) {
281+
Log_OC.e(TAG, "Trying to open a NULL OCFile");
282+
return;
283+
}
269284

270-
List<ResolveInfo> launchables = fileActivity.getPackageManager().
271-
queryIntentActivities(openFileWithIntent, PackageManager.GET_RESOLVED_FILTER);
285+
final Intent openFileWithIntent = createOpenFileIntent(file);
272286

273-
if (launchables.isEmpty()) {
274-
Optional<User> optionalUser = fileActivity.getUser();
287+
List<ResolveInfo> availableApps = fileActivity.getPackageManager().
288+
queryIntentActivities(openFileWithIntent, PackageManager.GET_RESOLVED_FILTER);
275289

276-
if (optionalUser.isPresent() && editorUtils.isEditorAvailable(optionalUser.get(), file.getMimeType())) {
277-
openFileWithTextEditor(file, fileActivity);
278-
} else {
279-
Account account = fileActivity.getAccount();
280-
OCCapability capability = fileActivity.getStorageManager().getCapability(account.name);
281-
if (capability.getRichDocumentsMimeTypeList().contains(file.getMimeType()) &&
282-
capability.getRichDocumentsDirectEditing().isTrue()) {
283-
openFileAsRichDocument(file, fileActivity);
284-
return;
285-
} else {
286-
DisplayUtils.showSnackMessage(fileActivity, R.string.file_list_no_app_for_file_type);
287-
return;
288-
}
289-
}
290+
if (availableApps.isEmpty()) {
291+
Optional<User> optionalUser = fileActivity.getUser();
292+
293+
if (optionalUser.isPresent() && editorUtils.isEditorAvailable(optionalUser.get(), file.getMimeType())) {
294+
openFileWithTextEditor(file, fileActivity);
295+
return;
290296
}
291297

292-
fileActivity.showLoadingDialog(fileActivity.getResources().getString(R.string.sync_in_progress));
293-
new Thread(new Runnable() {
294-
@Override
295-
public void run() {
296-
User user = currentAccount.getUser();
297-
FileDataStorageManager storageManager =
298-
new FileDataStorageManager(user, fileActivity.getContentResolver());
299-
// a fresh object is needed; many things could have occurred to the file
300-
// since it was registered to observe again, assuming that local files
301-
// are linked to a remote file AT MOST, SOMETHING TO BE DONE;
302-
SynchronizeFileOperation sfo = new SynchronizeFileOperation(file,
303-
null,
304-
user,
305-
true,
306-
fileActivity,
307-
storageManager,
308-
false);
309-
RemoteOperationResult result = sfo.execute(fileActivity);
310-
fileActivity.dismissLoadingDialog();
311-
if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
312-
// ISSUE 5: if the user is not running the app (this is a service!),
313-
// this can be very intrusive; a notification should be preferred
314-
Intent intent = ConflictsResolveActivity.createIntent(file,
315-
user,
316-
-1,
317-
Intent.FLAG_ACTIVITY_NEW_TASK,
318-
fileActivity);
319-
fileActivity.startActivity(intent);
320-
} else {
321-
if (!launchables.isEmpty()) {
322-
try {
323-
if (!result.isSuccess()) {
324-
DisplayUtils.showSnackMessage(fileActivity, R.string.file_not_synced);
325-
try {
326-
Thread.sleep(3000);
327-
} catch (InterruptedException e) {
328-
Log_OC.e(TAG, "Failed to sleep");
329-
}
330-
}
331-
332-
openFileWithIntent.setFlags(openFileWithIntent.getFlags() |
333-
Intent.FLAG_ACTIVITY_NEW_TASK);
334-
fileActivity.startActivity(openFileWithIntent);
335-
} catch (ActivityNotFoundException exception) {
336-
DisplayUtils.showSnackMessage(fileActivity, R.string.file_list_no_app_for_file_type);
337-
}
338-
} else {
339-
DisplayUtils.showSnackMessage(fileActivity, R.string.file_list_no_app_for_file_type);
340-
}
341-
}
298+
openRichDocumentFileWithoutAvailableApps(file);
342299

300+
return;
301+
}
302+
303+
fileActivity.showLoadingDialog(fileActivity.getResources().getString(R.string.sync_in_progress));
304+
305+
new Thread(() -> {
306+
User user = currentAccount.getUser();
307+
final var storageManager = new FileDataStorageManager(user, fileActivity.getContentResolver());
308+
// a fresh object is needed; many things could have occurred to the file
309+
// since it was registered to observe again, assuming that local files
310+
// are linked to a remote file AT MOST, SOMETHING TO BE DONE;
311+
final var sfo = new SynchronizeFileOperation(file,null, user, true, fileActivity, storageManager, false);
312+
final var result = sfo.execute(fileActivity);
313+
314+
fileActivity.dismissLoadingDialog();
315+
if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
316+
// ISSUE 5: if the user is not running the app (this is a service!),
317+
// this can be very intrusive; a notification should be preferred
318+
Intent intent = ConflictsResolveActivity.createIntent(file,
319+
user,
320+
-1,
321+
Intent.FLAG_ACTIVITY_NEW_TASK,
322+
fileActivity);
323+
fileActivity.startActivity(intent);
324+
return;
325+
}
326+
327+
if (availableApps.isEmpty()) {
328+
fileActivity.runOnUiThread(() -> DisplayUtils.showSnackMessage(fileActivity, R.string.file_list_no_app_for_file_type));
329+
330+
return;
331+
}
332+
333+
if (!result.isSuccess()) {
334+
fileActivity.runOnUiThread(() -> DisplayUtils.showSnackMessage(fileActivity, R.string.file_not_synced));
335+
336+
// Sleep to show snackbar message
337+
try {
338+
Thread.sleep(1000);
339+
} catch (InterruptedException e) {
340+
Log_OC.e(TAG, "Failed to sleep");
343341
}
344-
}).start();
342+
}
345343

346-
} else {
347-
Log_OC.e(TAG, "Trying to open a NULL OCFile");
348-
}
344+
fileActivity.runOnUiThread(() -> {
345+
try {
346+
openFileWithIntent.setFlags(openFileWithIntent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
347+
fileActivity.startActivity(openFileWithIntent);
348+
} catch (ActivityNotFoundException exception) {
349+
DisplayUtils.showSnackMessage(fileActivity, R.string.file_list_no_app_for_file_type);
350+
}
351+
});
352+
}).start();
349353
}
350354

351355
public void openFileAsRichDocument(OCFile file, Context context) {
@@ -376,19 +380,16 @@ public void openRichWorkspaceWithTextEditor(OCFile file, String url, Context con
376380
@NonNull
377381
private Intent createOpenFileIntent(OCFile file) {
378382
String storagePath = file.getStoragePath();
379-
Uri fileUri = getFileUri(file, MainApp.getAppContext().getResources().getStringArray(R.array
380-
.ms_office_extensions));
383+
Uri fileUri = file.getExposedFileUri(fileActivity);
384+
381385
Intent openFileWithIntent = null;
382386
int lastIndexOfDot = storagePath.lastIndexOf('.');
383387
if (lastIndexOfDot >= 0) {
384388
String fileExt = storagePath.substring(lastIndexOfDot + 1);
385389
String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExt);
386390
if (guessedMimeType != null) {
387391
openFileWithIntent = new Intent(Intent.ACTION_VIEW);
388-
openFileWithIntent.setDataAndType(
389-
fileUri,
390-
guessedMimeType
391-
);
392+
openFileWithIntent.setDataAndType(fileUri, guessedMimeType);
392393
}
393394
}
394395

@@ -398,25 +399,12 @@ private Intent createOpenFileIntent(OCFile file) {
398399

399400
if (openFileWithIntent == null) {
400401
openFileWithIntent = new Intent(Intent.ACTION_VIEW);
401-
openFileWithIntent.setDataAndType(
402-
fileUri,
403-
file.getMimeType()
404-
);
402+
openFileWithIntent.setDataAndType(fileUri, file.getMimeType());
405403
}
406404

407405
openFileWithIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
408-
return openFileWithIntent;
409-
}
410406

411-
private Uri getFileUri(OCFile file, String... officeExtensions) {
412-
if (file.getFileName().contains(".") &&
413-
Arrays.asList(officeExtensions).contains(file.getFileName().substring(file.getFileName().
414-
lastIndexOf(".") + 1)) &&
415-
!file.getStoragePath().startsWith(MainApp.getAppContext().getFilesDir().getAbsolutePath())) {
416-
return file.getLegacyExposedFileUri();
417-
} else {
418-
return file.getExposedFileUri(fileActivity);
419-
}
407+
return openFileWithIntent;
420408
}
421409

422410
public void streamMediaFile(OCFile file) {
@@ -1063,7 +1051,7 @@ public void uploadFromCamera(Activity activity, int requestCode, boolean isVideo
10631051
File cameraFile = createCameraFile(activity, isVideo);
10641052

10651053
Uri cameraUri = FileProvider.getUriForFile(activity.getApplicationContext(),
1066-
activity.getResources().getString(R.string.file_provider_authority), cameraFile);
1054+
activity.getResources().getString(R.string.file_provider_authority), cameraFile);
10671055
intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraUri);
10681056

10691057
if (intent.resolveActivity(activity.getPackageManager()) != null) {

app/src/main/res/values/arrays.xml

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)