X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/2ada53c99b44e548615dfb9d2456f4e2f1930414..3cae3d3eb84a0b734ee9ca8a27ee7df29232d90e:/src/com/owncloud/android/ui/activity/FileDisplayActivity.java diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index a83f5a09..2469dcf7 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -31,6 +31,7 @@ import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; +import android.content.ContentUris; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -41,10 +42,14 @@ import android.content.SyncRequest; import android.content.res.Resources.NotFoundException; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.os.IBinder; import android.preference.PreferenceManager; +import android.provider.DocumentsContract; import android.provider.MediaStore; +import android.provider.OpenableColumns; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -78,8 +83,10 @@ import com.owncloud.android.lib.common.network.CertificateCombinedException; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.operations.CreateFolderOperation; import com.owncloud.android.operations.CreateShareOperation; +import com.owncloud.android.operations.MoveFileOperation; import com.owncloud.android.operations.RemoveFileOperation; import com.owncloud.android.operations.RenameFileOperation; import com.owncloud.android.operations.SynchronizeFileOperation; @@ -87,6 +94,7 @@ import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.syncadapter.FileSyncAdapter; +import com.owncloud.android.ui.adapter.FileListListAdapter; import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; @@ -99,7 +107,6 @@ import com.owncloud.android.ui.preview.PreviewMediaFragment; import com.owncloud.android.ui.preview.PreviewVideoActivity; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.ErrorMessageAdapter; -import com.owncloud.android.utils.Log_OC; /** @@ -110,8 +117,9 @@ import com.owncloud.android.utils.Log_OC; */ public class FileDisplayActivity extends HookActivity implements -FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener { - +FileFragment.ContainerActivity, OnNavigationListener, +OnSslUntrustedCertListener, OnEnforceableRefreshListener { + private ArrayAdapter mDirectories; private SyncBroadcastReceiver mSyncBroadcastReceiver; @@ -135,6 +143,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; private static final int ACTION_SELECT_MULTIPLE_FILES = 2; + public static final int ACTION_MOVE_FILES = 3; private static final String TAG = FileDisplayActivity.class.getSimpleName(); @@ -148,7 +157,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener private String DIALOG_UNTRUSTED_CERT; private OCFile mWaitingToSend; - + @Override protected void onCreate(Bundle savedInstanceState) { Log_OC.d(TAG, "onCreate() start"); @@ -246,7 +255,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener Log_OC.e(TAG, "Initializing Fragments in onAccountChanged.."); initFragmentsWithFile(); if (file.isFolder()) { - startSyncFolderOperation(file); + startSyncFolderOperation(file, false); } } else { @@ -287,7 +296,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener if (listOfFiles != null) { listOfFiles.listDirectory(getCurrentDir()); } else { - Log.e(TAG, "Still have a chance to lose the initializacion of list fragment >("); + Log_OC.e(TAG, "Still have a chance to lose the initializacion of list fragment >("); } /// Second fragment @@ -303,12 +312,12 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener } } else { - Log.wtf(TAG, "initFragments() called with invalid NULLs!"); + Log_OC.wtf(TAG, "initFragments() called with invalid NULLs!"); if (getAccount() == null) { - Log.wtf(TAG, "\t account is NULL"); + Log_OC.wtf(TAG, "\t account is NULL"); } if (getFile() == null) { - Log.wtf(TAG, "\t file is NULL"); + Log_OC.wtf(TAG, "\t file is NULL"); } } } @@ -501,6 +510,40 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener } break; } + case R.id.action_sort: { + SharedPreferences appPreferences = PreferenceManager + .getDefaultSharedPreferences(this); + + // Read sorting order, default to sort by name ascending + Integer sortOrder = appPreferences + .getInt("sortOrder", FileListListAdapter.SORT_NAME); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.actionbar_sort_title) + .setSingleChoiceItems(R.array.actionbar_sortby, sortOrder , new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + + switch (which){ + case 0: + sortByName(true); + break; + case 1: + sortByDate(false); + break; + +// TODO re-enable when server-side folder size calculation is available +// case 2: +// sortBySize(false); +// break; + } + + dialog.dismiss(); + + } + }); + builder.create().show(); + break; + } default: retval = super.onOptionsItemSelected(item); } @@ -566,6 +609,20 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) { requestMultipleUpload(data, resultCode); + } else if (requestCode == ACTION_MOVE_FILES && (resultCode == RESULT_OK || + resultCode == MoveActivity.RESULT_OK_AND_MOVE)){ + + final Intent fData = data; + final int fResultCode = resultCode; + getHandler().postDelayed( + new Runnable() { + @Override + public void run() { + requestMoveOperation(fData, fResultCode); + } + }, + DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS + ); } } @@ -636,7 +693,34 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener } if (!remotepath.endsWith(OCFile.PATH_SEPARATOR)) remotepath += OCFile.PATH_SEPARATOR; - remotepath += new File(filepath).getName(); + + if (filepath.startsWith("content://")) { + // The query, since it only applies to a single document, will only return + // one row. There's no need to filter, sort, or select fields, since we want + // all fields for one document. + Cursor cursor = MainApp.getAppContext().getContentResolver() + .query(Uri.parse(filepath), null, null, null, null, null); + + try { + // moveToFirst() returns false if the cursor has 0 rows. Very handy for + // "if there's anything to look at, look at it" conditionals. + if (cursor != null && cursor.moveToFirst()) { + + // Note it's called "Display Name". This is + // provider-specific, and might not necessarily be the file name. + String displayName = cursor.getString( + cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + Log.i(TAG, "Display Name: " + displayName); + + remotepath += displayName; + } + } finally { + cursor.close(); + } + + } else { + remotepath += new File(filepath).getName(); + } i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath); i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath); @@ -646,6 +730,18 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener startService(i); } + /** + * Request the operation for moving the file/folder from one path to another + * + * @param data Intent received + * @param resultCode Result code received + */ + private void requestMoveOperation(Intent data, int resultCode) { + OCFile folderToMoveAt = (OCFile) data.getParcelableExtra(MoveActivity.EXTRA_CURRENT_FOLDER); + OCFile targetFile = (OCFile) data.getParcelableExtra(MoveActivity.EXTRA_TARGET_FILE); + getFileOperationsHelper().moveFile(folderToMoveAt, targetFile); + } + @Override public void onBackPressed() { OCFileListFragment listOfFiles = getListOfFilesFragment(); @@ -803,26 +899,158 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener return dialog; } - /** - * Translates a content URI of an image to a physical path - * on the disk + * Translates a content URI of an content to a physical path on the disk + * * @param uri The URI to resolve - * @return The path to the image or null if it could not be found + * @return The path to the content or null if it could not be found */ public String getPath(Uri uri) { - String[] projection = { MediaStore.Images.Media.DATA }; - Cursor cursor = managedQuery(uri, projection, null, null, null); - if (cursor != null) { - int column_index = cursor - .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); - cursor.moveToFirst(); - return cursor.getString(column_index); - } + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKat && DocumentsContract.isDocumentUri(getApplicationContext(), uri)) { + // ExternalStorageProvider + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + } + // DownloadsProvider + else if (isDownloadsDocument(uri)) { + + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), + Long.valueOf(id)); + + return getDataColumn(getApplicationContext(), contentUri, null, null); + } + // MediaProvider + else if (isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[] { split[1] }; + + return getDataColumn(getApplicationContext(), contentUri, selection, selectionArgs); + } + // Documents providers returned as content://... + else if (isAContentDocument(uri)) { + return uri.toString(); + } + } + // MediaStore (and general) + else if ("content".equalsIgnoreCase(uri.getScheme())) { + + // Return the remote address + if (isGooglePhotosUri(uri)) + return uri.getLastPathSegment(); + + return getDataColumn(getApplicationContext(), uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } return null; } /** + * Get the value of the data column for this Uri. This is useful for + * MediaStore Uris, and other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @param selection (Optional) Filter used in the query. + * @param selectionArgs (Optional) Selection arguments used in the query. + * @return The value of the _data column, which is typically a file path. + */ + public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { column }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + if (cursor != null && cursor.moveToFirst()) { + + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } finally { + if (cursor != null) + cursor.close(); + } + return null; + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + */ + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + */ + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + */ + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is Google Photos. + */ + public static boolean isGooglePhotosUri(Uri uri) { + return "com.google.android.apps.photos.content".equals(uri.getAuthority()); + } + + /** + * + * @param uri The Uri to check. + * @return Whether the Uri authority is Google Drive. + */ + public static boolean isGoogleDriveDocument(Uri uri) { + return "com.google.android.apps.docs.storage".equals(uri.getAuthority()); + } + + /** + * + * @param uri The Uri to check. + * @return Whether the Uri is from a content provider as kind "content://..." + */ + public static boolean isAContentDocument(Uri uri) { + return uri.toString().startsWith("content://"); + } + + /** * Pushes a directory to the drop down list * @param directory to push * @throws IllegalArgumentException If the {@link OCFile#isFolder()} returns false. @@ -1010,7 +1238,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener } ocFileListFragment.setMessageForEmptyList(getString(message)); } else { - Log.e(TAG, "OCFileListFragment is null"); + Log_OC.e(TAG, "OCFileListFragment is null"); } } @@ -1137,7 +1365,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH); listOfFiles.listDirectory(root); setFile(listOfFiles.getCurrentFile()); - startSyncFolderOperation(root); + startSyncFolderOperation(root, false); } cleanSecondFragment(); } @@ -1152,7 +1380,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener setNavigationListWithFolder(folder); listOfFiles.listDirectory(folder); setFile(listOfFiles.getCurrentFile()); - startSyncFolderOperation(folder); + startSyncFolderOperation(folder, false); } else { Log_OC.e(TAG, "Unexpected null when accessing list fragment"); } @@ -1171,7 +1399,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener cleanSecondFragment(); // Sync Folder - startSyncFolderOperation(directory); + startSyncFolderOperation(directory, false); } @@ -1288,7 +1516,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener @Override public void onSavedCertificate() { - startSyncFolderOperation(getCurrentDir()); + startSyncFolderOperation(getCurrentDir(), false); } @@ -1331,7 +1559,9 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener } else if (operation instanceof UnshareLinkOperation) { onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result); - } + } else if (operation instanceof MoveFileOperation) { + onMoveFileOperationFinish((MoveFileOperation)operation, result); + } } @@ -1410,12 +1640,13 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener /** - * Updates the view associated to the activity after the finish of an operation trying create a new folder + * Updates the view associated to the activity after the finish of an operation trying to move a + * file. * - * @param operation Creation operation performed. - * @param result Result of the creation. + * @param operation Move operation performed. + * @param result Result of the move operation. */ - private void onCreateFolderOperationFinish(CreateFolderOperation operation, RemoteOperationResult result) { + private void onMoveFileOperationFinish(MoveFileOperation operation, RemoteOperationResult result) { if (result.isSuccess()) { dismissLoadingDialog(); refreshListOfFilesFragment(); @@ -1502,6 +1733,30 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener } } + /** + * Updates the view associated to the activity after the finish of an operation trying create a new folder + * + * @param operation Creation operation performed. + * @param result Result of the creation. + */ + private void onCreateFolderOperationFinish(CreateFolderOperation operation, RemoteOperationResult result) { + if (result.isSuccess()) { + dismissLoadingDialog(); + refreshListOfFilesFragment(); + } else { + dismissLoadingDialog(); + try { + Toast msg = Toast.makeText(FileDisplayActivity.this, + ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), + Toast.LENGTH_LONG); + msg.show(); + + } catch (NotFoundException e) { + Log_OC.e(TAG, "Error while trying to show fail message " , e); + } + } + } + /** * {@inheritDoc} @@ -1549,7 +1804,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener return null; } - public void startSyncFolderOperation(OCFile folder) { + public void startSyncFolderOperation(OCFile folder, boolean ignoreETag) { long currentSyncTime = System.currentTimeMillis(); mSyncInProgress = true; @@ -1559,6 +1814,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener currentSyncTime, false, getFileOperationsHelper().isSharedSupported(), + ignoreETag, getStorageManager(), getAccount(), getApplicationContext() @@ -1670,4 +1926,37 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener onTransferStateChanged(file, false, false); } + @Override + public void onRefresh(boolean ignoreETag) { + refreshList(ignoreETag); + } + + @Override + public void onRefresh() { + refreshList(true); + } + + private void refreshList(boolean ignoreETag) { + OCFileListFragment listOfFiles = getListOfFilesFragment(); + if (listOfFiles != null) { + OCFile folder = listOfFiles.getCurrentFile(); + if (folder != null) { + /*mFile = mContainerActivity.getStorageManager().getFileById(mFile.getFileId()); + listDirectory(mFile);*/ + startSyncFolderOperation(folder, ignoreETag); + } + } + } + + private void sortByDate(boolean ascending){ + getListOfFilesFragment().sortByDate(ascending); + } + + private void sortBySize(boolean ascending){ + getListOfFilesFragment().sortBySize(ascending); + } + + private void sortByName(boolean ascending){ + getListOfFilesFragment().sortByName(ascending); + } }