diff options
author | Michael Weghorn <m.weghorn@posteo.de> | 2021-03-19 14:29:36 +0100 |
---|---|---|
committer | Michael Weghorn <m.weghorn@posteo.de> | 2021-03-22 07:57:51 +0100 |
commit | d678ee309b02b4cc8af29a097bf5053b8b1b4e06 (patch) | |
tree | a5e28a1540e355a7a0ac9493a73c638bc65e6f66 /android | |
parent | 2df8b776e635efc5e59aaf6c8a5a7f4c218d74d0 (diff) |
tdf#129833 android: Allow opening files using system file picker
Extend Android Viewer with the possibility to select a file to
open using the "system file picker", which can be opened by
an Intent that has the action 'Intent.ACTION_OPEN_DOCUMENT'
(or 'Intent.ACTION_GET_CONTENT' for API level < 19) set.
This way, all locations supported by currently installed and
set up DocumentsProviders [1] are generally supported.
In a test, opening local files worked just fine, but trying
to open a file located in a NextCloud share failed
(with the corresponding app [2] installed), showing this
in ADB log:
I DownloadFileOperation: Download of /Documents/five_pages.odt to /storage/emulated/0/Android/media/com.nextcloud.client/nextcloud/<USERNAME>@demo2.nextcloud.com/Documents/five_pages.odt: Unexpected exception
E DocumentsStorageProvider: RemoteOperationResult(mSuccess=false, mHttpCode=-1, mHttpPhrase=null, mException=android.os.NetworkOnMainThreadException, mCode=HOST_NOT_AVAILABLE, message=null, getLogMessage=Unexpected exception)
This will be dealt with in a separate commit.
For now, this way to open files (and a corresponding menu
entry) is added in addition to the existing ones, but
since that method should in general be able to cover all of
the other use cases as well, the other options may be
dropped in the future.
[1] https://developer.android.com/reference/android/provider/DocumentsProvider
[2] https://github.com/nextcloud/android
Change-Id: I684a4aa770c0df7cc9fc35ff92445230405885f5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112768
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Diffstat (limited to 'android')
7 files changed, 139 insertions, 0 deletions
diff --git a/android/source/res/drawable-hdpi/ic_folder_grey_144dp.xml b/android/source/res/drawable-hdpi/ic_folder_grey_144dp.xml new file mode 100644 index 000000000000..4ba799e20ef1 --- /dev/null +++ b/android/source/res/drawable-hdpi/ic_folder_grey_144dp.xml @@ -0,0 +1,5 @@ +<vector android:autoMirrored="true" android:height="144dp" + android:viewportHeight="24.0" android:viewportWidth="24.0" + android:width="144dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="#FF606060" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/> +</vector> diff --git a/android/source/res/layout/activity_document_browser.xml b/android/source/res/layout/activity_document_browser.xml index 8e17a3e1624f..b3b4ace2a465 100644 --- a/android/source/res/layout/activity_document_browser.xml +++ b/android/source/res/layout/activity_document_browser.xml @@ -104,6 +104,26 @@ android:background="@color/background_normal" android:orientation="vertical" /> + <!--Icon and text to open system file picker via Intent --> + <LinearLayout + android:id="@+id/system_file_picker_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/colorButtonNormal" + android:orientation="horizontal" + app:layout_constraintTop_toBottomOf="@id/toolbar"> + + <TextView + android:id="@+id/open_file_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:drawableLeft="@drawable/ic_folder_grey_144dp" + android:gravity="center_vertical" + android:text="@string/select_file_to_open" + android:textSize="24dp" /> + </LinearLayout> + </LinearLayout> </android.support.v4.widget.NestedScrollView> diff --git a/android/source/res/menu/navigation_menu.xml b/android/source/res/menu/navigation_menu.xml index 4098b27b8cac..ef6354b5dcff 100644 --- a/android/source/res/menu/navigation_menu.xml +++ b/android/source/res/menu/navigation_menu.xml @@ -19,6 +19,11 @@ <item android:id="@+id/menu_provider_otg" android:title="@string/otg_file_system" android:icon="@drawable/ic_usb_black_24dp"/> + + <item android:id="@+id/menu_system_file_dialog" + android:title="@string/system_file_selector" + android:icon="@drawable/ic_folder_black_24dp" /> + </group> <group android:orderInCategory="100"> diff --git a/android/source/res/values-de/strings.xml b/android/source/res/values-de/strings.xml index 64eaa844a754..4c6e25342ef7 100644 --- a/android/source/res/values-de/strings.xml +++ b/android/source/res/values-de/strings.xml @@ -22,6 +22,9 @@ <string name="new_drawing">Neue Zeichnung</string> <string name="default_document_name">unbenannt</string> + <string name="system_file_selector">System-Dateidialog</string> + <string name="select_file_to_open">Datei zum Öffnen auswählen</string> + <string name="browser_app_name">LibreOffice Browser</string> <string name="menu_search">Suchen</string> <string name="list_view">Liste</string> diff --git a/android/source/res/values/strings.xml b/android/source/res/values/strings.xml index a44d81ee5faf..8205176df685 100644 --- a/android/source/res/values/strings.xml +++ b/android/source/res/values/strings.xml @@ -22,6 +22,9 @@ <string name="new_drawing">New Drawing</string> <string name="default_document_name">untitled</string> + <string name="system_file_selector">System File Dialog</string> + <string name="select_file_to_open">Select file to open</string> + <string name="browser_app_name">LibreOffice Browser</string> <string name="menu_search">Search</string> <string name="list_view">List</string> diff --git a/android/source/src/java/org/libreoffice/ui/FileUtilities.java b/android/source/src/java/org/libreoffice/ui/FileUtilities.java index 7a58486004cd..28f1906a6369 100644 --- a/android/source/src/java/org/libreoffice/ui/FileUtilities.java +++ b/android/source/src/java/org/libreoffice/ui/FileUtilities.java @@ -56,6 +56,7 @@ public class FileUtilities { private static final Map<String, String> extensionToMimeTypeMap = new HashMap<String, String>(); static { // Please keep this in sync with AndroidManifest.xml + // and 'SUPPORTED_MIME_TYPES' in LibreOfficeUIActivity.java // ODF mExtnMap.put(".odt", DOC); diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java index f52972b86f26..8e84868dbda5 100644 --- a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java +++ b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java @@ -12,6 +12,7 @@ package org.libreoffice.ui; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; +import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -127,9 +128,51 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings public static final String NEW_CALC_STRING_KEY = "private:factory/scalc"; public static final String NEW_DRAW_STRING_KEY = "private:factory/sdraw"; + // keep this in sync with 'AndroidManifext.xml' + private static final String[] SUPPORTED_MIME_TYPES = { + "application/vnd.oasis.opendocument.text", + "application/vnd.oasis.opendocument.graphics", + "application/vnd.oasis.opendocument.presentation", + "application/vnd.oasis.opendocument.spreadsheet", + "application/vnd.oasis.opendocument.text-flat-xml", + "application/vnd.oasis.opendocument.graphics-flat-xml", + "application/vnd.oasis.opendocument.presentation-flat-xml", + "application/vnd.oasis.opendocument.spreadsheet-flat-xml", + "application/vnd.oasis.opendocument.text-template", + "application/vnd.oasis.opendocument.spreadsheet-template", + "application/vnd.oasis.opendocument.graphics-template", + "application/vnd.oasis.opendocument.presentation-template", + "application/rtf", + "text/rtf", + "application/msword", + "application/vnd.ms-powerpoint", + "application/vnd.ms-excel", + "application/vnd.visio", + "application/vnd.visio.xml", + "application/x-mspublisher", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.openxmlformats-officedocument.wordprocessingml.template", + "application/vnd.openxmlformats-officedocument.spreadsheetml.template", + "application/vnd.openxmlformats-officedocument.presentationml.template", + "text/csv", + "text/comma-separated-values", + "application/vnd.ms-works", + "application/vnd.apple.keynote", + "application/x-abiword", + "application/x-pagemaker", + "image/x-emf", + "image/x-svm", + "image/x-wmf", + "image/svg+xml", + }; + public static final int GRID_VIEW = 0; public static final int LIST_VIEW = 1; + private static final int REQUEST_CODE_OPEN_FILECHOOSER = 12345; + private DrawerLayout drawerLayout; private NavigationView navigationDrawer; private ActionBar actionBar; @@ -151,6 +194,8 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings private LinearLayout writerLayout; private LinearLayout impressLayout; private LinearLayout calcLayout; + private LinearLayout systemFilePickerLayout; + private TextView openFileView; @Override public void onCreate(Bundle savedInstanceState) { @@ -207,6 +252,8 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings impressLayout = findViewById(R.id.impressLayout); calcLayout = findViewById(R.id.calcLayout); drawLayout = findViewById(R.id.drawLayout); + openFileView = findViewById(R.id.open_file_view); + openFileView.setOnClickListener(this); recentRecyclerView = findViewById(R.id.list_recent); @@ -228,6 +275,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings recentRecyclerView.setAdapter(new RecentFilesAdapter(this, recentFiles)); fileRecyclerView = findViewById(R.id.file_recycler_view); + systemFilePickerLayout = findViewById(R.id.system_file_picker_layout); //This should be tested because it possibly disables view recycling fileRecyclerView.setNestedScrollingEnabled(false); openDirectory(currentDirectory); @@ -277,6 +325,11 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings return true; } + case R.id.menu_system_file_dialog: { + switchToSystemFileDialogLayout(); + return true; + } + default: return false; } @@ -306,6 +359,9 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings drawerToggle.setDrawerIndicatorEnabled(true); drawerLayout.addDrawerListener(drawerToggle); drawerToggle.syncState(); + + // initially show layout with item to open system file picker + switchToSystemFileDialogLayout(); } private void expandFabMenu() { @@ -418,7 +474,43 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings return viewMode == LIST_VIEW; } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_CODE_OPEN_FILECHOOSER && resultCode == RESULT_OK) { + final Uri fileUri = data.getData(); + + // "forward" to LibreOfficeMainActivity to open the file + Intent intent = new Intent(Intent.ACTION_VIEW, fileUri); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + String packageName = getApplicationContext().getPackageName(); + ComponentName componentName = new ComponentName(packageName, + LibreOfficeMainActivity.class.getName()); + intent.setComponent(componentName); + startActivity(intent); + } + } + + private void showSystemFilePickerAndOpenFile() { + Intent intent = new Intent(); + try { + intent.setAction(Intent.ACTION_OPEN_DOCUMENT); + } catch (ActivityNotFoundException exception) { + // Intent.ACTION_OPEN_DOCUMENT added in API level 19, but minSdkVersion is currently 16 + intent.setAction(Intent.ACTION_GET_CONTENT); + } + + intent.setType("*/*"); + intent.putExtra(Intent.EXTRA_MIME_TYPES, SUPPORTED_MIME_TYPES);; + + if (intent.resolveActivity(getPackageManager()) != null) { + startActivityForResult(intent, REQUEST_CODE_OPEN_FILECHOOSER); + } + } + + private void switchToDocumentProvider(IDocumentProvider provider) { + fileRecyclerView.setVisibility(View.VISIBLE); + systemFilePickerLayout.setVisibility(View.GONE); new AsyncTask<IDocumentProvider, Void, Void>() { @Override @@ -467,6 +559,13 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings }.execute(provider); } + private void switchToSystemFileDialogLayout() { + fileRecyclerView.setVisibility(View.GONE); + findViewById(R.id.text_directory_path).setVisibility(View.GONE); + systemFilePickerLayout.setVisibility(View.VISIBLE); + refreshView(); + } + public void openDirectory(IFile dir) { if (dir == null) return; @@ -1065,6 +1164,9 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings expandFabMenu(); } break; + case R.id.open_file_view: + showSystemFilePickerAndOpenFile(); + break; case R.id.newWriterFAB: createNewFileInputDialog(getString(R.string.default_document_name) + FileUtilities.DEFAULT_WRITER_EXTENSION, NEW_WRITER_STRING_KEY); break; |