[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-7-1+backports' - 10 commits - android/.gitignore android/source

Michael Weghorn (via logerrit) logerrit at kemper.freedesktop.org
Mon Apr 12 05:38:15 UTC 2021


 android/.gitignore                                                    |    1 
 android/source/build.gradle                                           |   26 -
 android/source/res/values-tr/strings.xml                              |    9 
 android/source/src/java/org/libreoffice/AboutDialogFragment.java      |   13 
 android/source/src/java/org/libreoffice/LOEvent.java                  |    8 
 android/source/src/java/org/libreoffice/LOKitShell.java               |    4 
 android/source/src/java/org/libreoffice/LOKitThread.java              |   23 -
 android/source/src/java/org/libreoffice/LOKitTileProvider.java        |   54 --
 android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java  |  221 ++++------
 android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java |   20 
 10 files changed, 142 insertions(+), 237 deletions(-)

New commits:
commit fba9d44884f48e8564b78246cbe44dc61a2b284b
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 17:04:15 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:35:15 2021 +0200

    android: Drop some unused Turkish translations
    
    Those are leftovers; they're unused since
    
        commit a23bd42e9b2f6401c710ac95afcc3aa8f360d65c
        Date:   Tue Apr 6 14:26:06 2021 +0200
    
            android: Drop custom file abstraction + UI
    
    Change-Id: I898391cfccd465e4d18d51ee07ee847978872ef1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113885
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit bcf0ed2f672646107b42cbe67e5c3c9d170bb33a)

diff --git a/android/source/res/values-tr/strings.xml b/android/source/res/values-tr/strings.xml
index fe2ee5958dcc..72d15c210933 100644
--- a/android/source/res/values-tr/strings.xml
+++ b/android/source/res/values-tr/strings.xml
@@ -58,15 +58,6 @@
     <string name="action_undo">Geri Al</string>
     <string name="action_redo">Yinele</string>
 
-    <!-- Directory browser strings -->
-    <string name="up_description">Üst dizin</string>
-    <string name="confirm_label">Onayla</string>
-    <string name="cancel_label">İptal</string>
-    <string name="search_label">Git</string>
-    <string name="directory_browser_label">Dizin Seç</string>
-    <string name="bad_directory">Geçersiz dizin</string>
-    <string name="current_dir">Şuan ki dizin: %1$s</string>
-
     <!-- Save Alert dialog strings -->
     <string name="save_alert_dialog_title">Değişiklikleri kaydetmek istiyor musunuz?</string>
     <string name="save_document">Kaydet</string>
commit f0b3f7321c8bef595ed3555a594d75901ce58802
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 16:50:06 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:35:08 2021 +0200

    android: Drop 'LibreOfficeMainActivity#onSaveInstanceState'
    
    It just calls the parent class method anyway.
    
    Change-Id: I802e75ad650b71d6daa08494ff812985bb844a5f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113884
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit c0c43f4742e9a78addafd9522779f7f55243a522)

diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index a1fab7dbde49..f751f2e7dd61 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -963,11 +963,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         mFormattingController.handleActivityResult(requestCode, resultCode, data);
         hideBottomToolbar();
     }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 5b83ba53dcdc8c92691685a318f1e5929ae67995
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 13:59:43 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:34:57 2021 +0200

    tdf#95517 android: Rework app/doc lifecycle handling
    
    Previously, the document was always closed in
    LibreOfficeMainActivity's 'onStop' and loaded anew in
    its 'onStart' method.
    In order to not lose user changes, there was also
    a caching mechanism in LOKitTileProvider, also triggered
    in 'LibreOfficeMainActivity#onStop'.
    
    This means that e.g. each time a switch to another
    Activity/app happened, a cache document with the user
    modifications in it should have been created for
    restoration. That did not really seem to work
    particularly well in a few tests, as also described
    in tdf#95517 ("changes reset after show Settings").
    
    The documentation aboue Activity lifecycle says [1]
    
    > The entire lifetime of an activity happens between the first call to
    > onCreate(Bundle) through to a single final call to onDestroy(). An
    > activity will do all setup of "global" state in onCreate(), and release
    > all remaining resources in onDestroy(). For example, if it has a thread
    > running in the background to download data from the network, it may
    > create that thread in onCreate() and then stop the thread in
    > onDestroy().
    
    This changes the handling to load the document in the
    'onCreate' method and clos it only in 'onDestroy',
    i.e. the document remains open while e.g. switching
    to another Activity or app, thus making it unnecessary
    to try to restore state as good as possible in 'onStart'.
    An invalidation of the view (via 'LOEvent.REFRESH')
    generally seems to be enough.
    (Well, sometimes there is an issue with
    invalidation/repaint and single tiles remain black,
    but that happened previously - when the whole doc
    was loaded anew - just the same way).
    
    This allows dropping some extra handling needed
    to try to restore the previous state, along with the
    caching mechanism in LOKitTileProvider (that had some
    other issues, e.g. it didn't reliably create the cache
    file, since the file extension was not always set, and
    'LOKitTileProvider#cacheDocument' was relying on that
    to derive the document type).
    
    I am not sure whether I missed any aspect that the
    previous implementation was trying to solve, but
    at least these scenarios I found and tested worked
    as expected with the change in place:
    
    * user changes still present after switching between apps
      (s. tdf#106648 "Android: save current work when onSaveInstanceState is
       called")
    * for the Calc case, the sheet that was selected before
      switching apps is still selected (s. tdf#101689
      "Android Viewer calc returns to first sheet")
    * user changes no longer get lost when selecting a menu item
      (s. tdf#95517 "changes reset after show Settings")
    * case where the user leaves the app by pressing Home, and starts it again
      (as described in commit 83386129f5be002f2649db81bba4c468c7f6e4de
      "android: Fix the application lifecycle.")
    
    [1] https://developer.android.com/reference/android/app/Activity#activity-lifecycle
    
    Change-Id: If59734cbfd62673884786066c94e2c2a1d6a916e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113883
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit 1bc42472200c32c9a0a10dd1c3cd6c6a8a5d47d2)

diff --git a/android/source/src/java/org/libreoffice/LOEvent.java b/android/source/src/java/org/libreoffice/LOEvent.java
index 74a09c92cc1d..d1170eee12ad 100644
--- a/android/source/src/java/org/libreoffice/LOEvent.java
+++ b/android/source/src/java/org/libreoffice/LOEvent.java
@@ -33,7 +33,6 @@ public class LOEvent implements Comparable<LOEvent> {
     public static final int SWIPE_LEFT = 12;
     public static final int NAVIGATION_CLICK = 13;
     public static final int UNO_COMMAND = 14;
-    public static final int RESUME = 15;
     public static final int LOAD_NEW = 16;
     public static final int SAVE_AS = 17;
     public static final int UPDATE_PART_PAGE_RECT = 18;
@@ -105,13 +104,6 @@ public class LOEvent implements Comparable<LOEvent> {
         mValue = value;
     }
 
-    public LOEvent(int type, String key, int value) {
-        mType = type;
-        mTypeString = "Resume partIndex";
-        mString = key;
-        mPartIndex = value;
-    }
-
     public LOEvent(String filePath, int type) {
         mType = type;
         mTypeString = "Load";
diff --git a/android/source/src/java/org/libreoffice/LOKitShell.java b/android/source/src/java/org/libreoffice/LOKitShell.java
index 75b2fb09b260..43dd30a69847 100644
--- a/android/source/src/java/org/libreoffice/LOKitShell.java
+++ b/android/source/src/java/org/libreoffice/LOKitShell.java
@@ -123,10 +123,6 @@ public class LOKitShell {
         LOKitShell.sendEvent(new LOEvent(filePath, fileFormat, LOEvent.SAVE_COPY_AS));
     }
 
-    public static void sendResumeEvent(String inputFile, int partIndex) {
-        LOKitShell.sendEvent(new LOEvent(LOEvent.RESUME, inputFile, partIndex));
-    }
-
     public static void sendCloseEvent() {
         LOKitShell.sendEvent(new LOEvent(LOEvent.CLOSE));
     }
diff --git a/android/source/src/java/org/libreoffice/LOKitThread.java b/android/source/src/java/org/libreoffice/LOKitThread.java
index a3c6733ad81f..1bca3cd13b5c 100644
--- a/android/source/src/java/org/libreoffice/LOKitThread.java
+++ b/android/source/src/java/org/libreoffice/LOKitThread.java
@@ -188,26 +188,6 @@ class LOKitThread extends Thread {
         mLayerClient.setZoomConstraints(new ZoomConstraints(true, 1f, minZoom, 0f));
     }
 
-
-    /**
-     * Resume the document with the current part
-     */
-
-    private void resumeDocument(String filename, int partIndex){
-
-        mLayerClient = mContext.getLayerClient();
-
-        mInvalidationHandler = new InvalidationHandler(mContext);
-        mTileProvider = TileProviderFactory.create(mContext, mInvalidationHandler, filename);
-
-        if (mTileProvider.isReady()) {
-            updateZoomConstraints();
-            changePart(partIndex);
-        } else {
-            closeDocument();
-        }
-    }
-
     /**
      * Change part of the document.
      */
@@ -310,9 +290,6 @@ class LOKitThread extends Thread {
             case LOEvent.SAVE_COPY_AS:
                 saveDocumentAs(event.filePath, event.fileType, false);
                 break;
-            case LOEvent.RESUME:
-                resumeDocument(event.mString, event.mPartIndex);
-                break;
             case LOEvent.CLOSE:
                 closeDocument();
                 break;
diff --git a/android/source/src/java/org/libreoffice/LOKitTileProvider.java b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
index aafdbff311c1..e9fc2d52a154 100644
--- a/android/source/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
@@ -74,31 +74,16 @@ class LOKitTileProvider implements TileProvider {
         mContext.setTileProvider(this);
         mInputFile = input;
         File f = new File(mInputFile);
-        final String cacheFile = mContext.getExternalCacheDir().getAbsolutePath() + "/lo_cached_" + f.getName();
-
-        if(mContext.firstStart){
-            File cacheFileObj = new File(cacheFile);
-            if(cacheFileObj.exists()) {
-                cacheFileObj.delete();
-            }
-            mContext.firstStart=false;
-        }
 
         Log.i(LOGTAG, "====> Loading file '" + input + "'");
-        File fileToBeEncoded;
-        if(isDocumentCached()){
-            fileToBeEncoded = new File(cacheFile);
-        }else{
-            fileToBeEncoded = new File(input);
 
-        }
+        File fileToBeEncoded = new File(input);
         String encodedFileName = android.net.Uri.encode(fileToBeEncoded.getName());
 
         mDocument = mOffice.documentLoad(
                 (new File(fileToBeEncoded.getParent(),encodedFileName)).getPath()
         );
 
-
         if (mDocument == null && !mContext.isPasswordProtected()) {
             Log.i(LOGTAG, "====> mOffice.documentLoad() returned null, trying to restart 'Office' and loading again");
             mOffice.destroy();
@@ -401,45 +386,10 @@ class LOKitTileProvider implements TileProvider {
         }
     }
 
-    public boolean isDocumentCached(){
-        File input = new File(mInputFile);
-        final String cacheFile = mContext.getExternalCacheDir().getAbsolutePath() + "/lo_cached_" + input.getName();
-        File cacheFileObj = new File(cacheFile);
-        if(cacheFileObj.exists())
-            return true;
-
-        return false;
-    }
-
-    public void cacheDocument() {
-        String cacheDir = mContext.getExternalCacheDir().getAbsolutePath();
-        File input = new File(mInputFile);
-        final String cacheFile = cacheDir + "/lo_cached_" + input.getName();
-        Log.i(LOGTAG, "cacheDocument: " + cacheFile);
-        if(isDocumentCached()){
-            LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Save"));
-        }else if(mDocument != null){
-            mDocument.saveAs("file://"+cacheFile, FileUtilities.getExtension(input.getPath()).substring(1),"");
-        }else{
-            Log.w(LOGTAG, "mDocument was null when trying to save cacheDocument: " + cacheFile);
-        }
-    }
-
     public void saveDocument(){
-        if(isDocumentCached()){
-            String format = FileUtilities.getExtension(mInputFile).substring(1);
-            String cacheDir = mContext.getExternalCacheDir().getAbsolutePath();
-            File input = new File(mInputFile);
-            final String cacheFile = cacheDir + "/lo_cached_" + input.getName();
-            String path = input.getAbsolutePath();
-            saveDocumentAs(path, format, true);
-            (new File(cacheFile)).delete();
-        }else{
-            mContext.saveDocument();
-        }
+        mContext.saveDocument();
     }
 
-
     private void setupDocumentFonts() {
         String values = mDocument.getCommandValues(".uno:CharFontName");
         if (values == null || values.isEmpty())
diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 950a063e8d94..a1fab7dbde49 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -8,7 +8,6 @@ import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.graphics.RectF;
 import android.net.Uri;
@@ -79,14 +78,12 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     private ListView mDrawerList;
     private List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>();
     private DocumentPartViewListAdapter mDocumentPartViewListAdapter;
-    private int partIndex=-1;
     private DocumentOverlay mDocumentOverlay;
     /** URI of the actual document. */
     private Uri mDocumentUri;
     /** Temporary local copy of the document. */
     private File mTempFile = null;
     private File mTempSlideShowFile = null;
-    public boolean firstStart = true;
 
     BottomSheetBehavior bottomToolbarSheetBehavior;
     BottomSheetBehavior toolbarColorPickerBottomSheetBehavior;
@@ -120,7 +117,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     private boolean isSearchToolbarOpen = false;
     private static boolean isDocumentChanged = false;
     private boolean isUNOCommandsToolbarOpen = false;
-    private boolean isNewDocument = false;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -171,6 +167,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         mDocumentOverlay = new DocumentOverlay(this, layerView);
 
         mbISReadOnlyMode = !isExperimentalMode();
+        boolean isNewDocument = false;
 
         mDocumentUri = getIntent().getData();
         if (mDocumentUri != null) {
@@ -182,6 +179,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
                     String newDocumentType = getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY);
                     // create a temporary local file, will be copied to the actual URI when saving
                     loadNewDocument(newDocumentType);
+                    isNewDocument = true;
                     isReadOnlyDoc = false;
                 } else {
                     isReadOnlyDoc = (getIntent().getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
@@ -211,6 +209,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
                 Log.e(LOGTAG, "couldn't create temporary file from " + mDocumentUri);
                 return;
             }
+            LOKitShell.sendLoadEvent(mTempFile.getPath());
         }
 
         mDrawerLayout = findViewById(R.id.drawer_layout);
@@ -277,7 +276,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         String tempFileName = "LibreOffice_" + UUID.randomUUID().toString();
         mTempFile = new File(this.getCacheDir(), tempFileName);
         LOKitShell.sendNewDocumentLoadEvent(mTempFile.getPath(), newDocumentType);
-        isNewDocument = true;
     }
 
     public RectF getCurrentCursorPosition() {
@@ -397,28 +395,20 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     protected void onStart() {
         Log.i(LOGTAG, "onStart..");
         super.onStart();
-        if (!isNewDocument){
-            if (partIndex == -1)
-                LOKitShell.sendLoadEvent(mTempFile.getPath());
-            else
-                LOKitShell.sendResumeEvent(mTempFile.getPath(), partIndex);
-        }
+        LOKitShell.sendEvent(new LOEvent(LOEvent.REFRESH));
     }
 
     @Override
     protected void onStop() {
         Log.i(LOGTAG, "onStop..");
-        //save document to cache
-        if (mTileProvider != null)
-            mTileProvider.cacheDocument();
         hideSoftKeyboardDirect();
-        LOKitShell.sendCloseEvent();
         super.onStop();
     }
 
     @Override
     protected void onDestroy() {
         Log.i(LOGTAG, "onDestroy..");
+        LOKitShell.sendCloseEvent();
         mLayerClient.destroy();
         super.onDestroy();
 
@@ -845,7 +835,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
             DocumentPartView partView = mDocumentPartViewListAdapter.getItem(position);
-            partIndex = partView.partIndex;
             LOKitShell.sendChangePartEvent(partView.partIndex);
             mDrawerLayout.closeDrawer(mDrawerList);
         }
commit e96853b5b1965d5c006bc2f819f3331b4bdc93f4
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 10:08:24 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:34:13 2021 +0200

    android: Always create a temporary local copy of the doc
    
    Always create a local copy of the original document
    to work with, rather than doing a different handling
    depending on the type of the URI used to specify the
    file to load.
    
    This will also simplify adding support for "Save As"
    in upcoming commits, where the temporary
    file can remain the same and only the URI for the
    actual document will need to be changed.
    
    Change-Id: I2587611fa56b76d8a5384ac25c57335e8d12e987
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113882
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit d8fea0b8cc92c3416df1e98d7f472e534eae38e8)

diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 0048bad50fd7..950a063e8d94 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -80,7 +80,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     private List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>();
     private DocumentPartViewListAdapter mDocumentPartViewListAdapter;
     private int partIndex=-1;
-    private File mInputFile;
     private DocumentOverlay mDocumentOverlay;
     /** URI of the actual document. */
     private Uri mDocumentUri;
@@ -183,38 +182,37 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
                     String newDocumentType = getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY);
                     // create a temporary local file, will be copied to the actual URI when saving
                     loadNewDocument(newDocumentType);
-                    mInputFile = mTempFile;
                     isReadOnlyDoc = false;
-                } else if (copyFileToTemp() && mTempFile != null) {
-                    mInputFile = mTempFile;
-                    isReadOnlyDoc = (getIntent().getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
                 } else {
-                    // TODO: can't open the file
-                    Log.e(LOGTAG, "couldn't create temporary file from " + mDocumentUri);
-                    return;
+                    isReadOnlyDoc = (getIntent().getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
                 }
 
                 mbISReadOnlyMode = !isExperimentalMode() || isReadOnlyDoc;
                 Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + mDocumentUri.getPath());
 
                 String displayName = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), mDocumentUri);
-                if (displayName.isEmpty()) {
-                    // fall back to using temp file name
-                    displayName = mInputFile.getName();
-                }
                 toolbarTop.setTitle(displayName);
 
             } else if (mDocumentUri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
-                mInputFile = new File(mDocumentUri.getPath());
                 mbISReadOnlyMode = true;
                 Log.d(LOGTAG, "SCHEME_FILE: getPath(): " + mDocumentUri.getPath());
-                toolbarTop.setTitle(mInputFile.getName());
+                toolbarTop.setTitle(mDocumentUri.getLastPathSegment());
             }
         } else {
             Log.e(LOGTAG, "No document specified. This should never happen.");
             return;
         }
 
+        if (!isNewDocument) {
+            // create a temporary local copy to work with
+            boolean copyOK = copyFileToTemp() && mTempFile != null;
+            if (!copyOK) {
+                // TODO: can't open the file
+                Log.e(LOGTAG, "couldn't create temporary file from " + mDocumentUri);
+                return;
+            }
+        }
+
         mDrawerLayout = findViewById(R.id.drawer_layout);
 
         if (mDocumentPartViewListAdapter == null) {
@@ -345,12 +343,12 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     }
 
     public void saveFileToOriginalSource() {
-        if (isReadOnlyMode() || mInputFile == null || mDocumentUri == null || !mDocumentUri.getScheme().equals(ContentResolver.SCHEME_CONTENT))
+        if (isReadOnlyMode() || mTempFile == null || mDocumentUri == null || !mDocumentUri.getScheme().equals(ContentResolver.SCHEME_CONTENT))
             return;
 
         boolean copyOK = false;
         try {
-            final FileInputStream inputStream = new FileInputStream(mInputFile);
+            final FileInputStream inputStream = new FileInputStream(mTempFile);
             final OutputStream outputStream = getContentResolver().openOutputStream(mDocumentUri);
             copyOK = copyStream(inputStream, outputStream);
         } catch (FileNotFoundException e) {
@@ -401,9 +399,9 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         super.onStart();
         if (!isNewDocument){
             if (partIndex == -1)
-                LOKitShell.sendLoadEvent(mInputFile.getPath());
+                LOKitShell.sendLoadEvent(mTempFile.getPath());
             else
-                LOKitShell.sendResumeEvent(mInputFile.getPath(), partIndex);
+                LOKitShell.sendResumeEvent(mTempFile.getPath(), partIndex);
         }
     }
 
@@ -785,7 +783,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
 
     // this function can only be called in InvalidationHandler.java
     public void setPassword() {
-        mTileProvider.setDocumentPassword("file://"+mInputFile.getPath(), mPassword);
+        mTileProvider.setDocumentPassword("file://" + mTempFile.getPath(), mPassword);
     }
 
     // setTileProvider is meant to let main activity have a handle of LOKit when dealing with password
@@ -943,7 +941,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
 
     public void preparePresentation() {
         if (getExternalCacheDir() != null) {
-            String tempPath = getExternalCacheDir().getPath() + "/" + mInputFile.getName() + ".svg";
+            String tempPath = getExternalCacheDir().getPath() + "/" + mTempFile.getName() + ".svg";
             mTempSlideShowFile = new File(tempPath);
             if (mTempSlideShowFile.exists() && !isDocumentChanged) {
                 startPresentation("file://" + tempPath);
commit b368623ad40ee27014fcf70898e22aabc6179255
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 10:08:19 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:33:20 2021 +0200

    android: Turn 3 "internal" docs into raw resources
    
    Make 'example.odt', 'license.txt' and 'notice.txt'
    (which can be opened via the "About" dialog)
    resources of the app by copying them to a new directory
    'res_generated' instead of into assets, and include
    'res_generated' into resources, then use an
    'android.resource://' URI instead of a 'file:///assets/'
    one in AboutDialogFragment.
    The latter does not work with when passed as a parameter
    to 'ContentResolver.openInputStream'.
    
    Adapt/Simplify 'LibreOfficeMainActivity#copyFileToTemp' to
    make loading those docs using the 'android.resource://'
    URI work and use the existing 'copyStream' method for copying from
    the input to the output stream.
    
    This is in preparation for upcoming commit with Change-Id
    I7731ef81a4242fa0ce3b3fd8ced1683a6a6bee8c,
    "android: Always create a temporary local copy of the doc".
    
    Change-Id: I7731ef81a4242fa0ce3b3fd8ced1683a6a6bee8c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113881
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit d3f8f4b1663214ebe29e49e109b1ae704b680b9e)

diff --git a/android/.gitignore b/android/.gitignore
index 163145dd63fa..de608fea3c14 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -6,6 +6,7 @@
 /source/build/
 /source/captures/
 /source/jni/Application.mk
+/source/res_generated
 /jniLibs/
 /source/liboSettings.gradle
 /source/local.properties
diff --git a/android/source/build.gradle b/android/source/build.gradle
index 35a83be655c0..35b3c601079e 100644
--- a/android/source/build.gradle
+++ b/android/source/build.gradle
@@ -42,7 +42,7 @@ android {
     sourceSets {
         main.manifest.srcFile 'AndroidManifest.xml'
         main.assets.srcDirs = ['assets']
-        main.res.srcDirs = ['res']
+        main.res.srcDirs = ['res', 'res_generated']
         main.java.srcDirs = ['../Bootstrap/src', 'src/java']
         main.jniLibs.srcDirs = ["${liboJniLibsdir}"]
         main.jni.srcDirs = [] // don't attempt to build native-lib via gradle
@@ -144,14 +144,6 @@ task copyUnpackAssets(type: Copy) {
 task copyAssets(type: Copy) {
     description "copies assets that can be accessed within the installed apk"
     into 'assets'
-    from("${liboInstdir}") {
-        includes = ["LICENSE", "NOTICE"]
-        rename "LICENSE", "license.txt"
-        rename "NOTICE", "notice.txt"
-    }
-    from("${liboExampleDocument}") {
-        rename ".*", "example.odt"
-    }
 
     // include icons
     into ('share') {
@@ -195,6 +187,19 @@ task copyAssets(type: Copy) {
     }
 }
 
+task copyAppResources(type: Copy) {
+    description "copies documents to make them available as app resources"
+    into 'res_generated/raw'
+    from("${liboInstdir}") {
+        includes = ["LICENSE", "NOTICE"]
+        rename "LICENSE", "license.txt"
+        rename "NOTICE", "notice.txt"
+    }
+    from("${liboExampleDocument}") {
+        rename ".*", "example.odt"
+    }
+}
+
 task createFullConfig(type: Copy) {
     // grab dir to clear whole hierarchy on clean target
     outputs.dir "assets_fullUI"
@@ -292,7 +297,8 @@ task createRCfiles {
 preBuild.dependsOn 'createRCfiles',
         'createStrippedConfigMain',
         'createStrippedConfigRegistry',
-        'createFullConfig'
+        'createFullConfig',
+        'copyAppResources'
 
 clean.dependsOn 'cleanCopyAssets',
         'cleanCreateStrippedConfig',
diff --git a/android/source/src/java/org/libreoffice/AboutDialogFragment.java b/android/source/src/java/org/libreoffice/AboutDialogFragment.java
index 6c944bae7ef1..8e4ddf0ae08c 100644
--- a/android/source/src/java/org/libreoffice/AboutDialogFragment.java
+++ b/android/source/src/java/org/libreoffice/AboutDialogFragment.java
@@ -30,9 +30,6 @@ import java.io.File;
 
 public class AboutDialogFragment extends DialogFragment {
 
-    private static final String DEFAULT_DOC_PATH = "/assets/example.odt";
-
-
     @NonNull @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
 
@@ -81,21 +78,21 @@ public class AboutDialogFragment extends DialogFragment {
                 .setNegativeButton(R.string.about_license, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int id) {
-                        loadFromAbout("/assets/license.txt");
+                        loadFromAbout(R.raw.license);
                         dialog.dismiss();
                     }
                 })
                 .setPositiveButton(R.string.about_notice, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int id) {
-                        loadFromAbout("/assets/notice.txt");
+                        loadFromAbout(R.raw.notice);
                         dialog.dismiss();
                     }
                 })
                 .setNeutralButton(R.string.about_moreinfo, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int id) {
-                        loadFromAbout(DEFAULT_DOC_PATH);
+                        loadFromAbout(R.raw.example);
                         dialog.dismiss();
                     }
                 });
@@ -103,8 +100,8 @@ public class AboutDialogFragment extends DialogFragment {
         return builder.create();
     }
 
-    private void loadFromAbout(String input) {
-        Intent i = new Intent(Intent.ACTION_VIEW, Uri.fromFile(new File(input)));
+    private void loadFromAbout(int resourceId) {
+        Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("android.resource://" + BuildConfig.APPLICATION_ID + "/" + resourceId));
         String packageName = getActivity().getApplicationContext().getPackageName();
         ComponentName componentName = new ComponentName(packageName, LibreOfficeMainActivity.class.getName());
         i.setComponent(componentName);
diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 022965e65052..0048bad50fd7 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -175,7 +175,8 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
 
         mDocumentUri = getIntent().getData();
         if (mDocumentUri != null) {
-            if (mDocumentUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
+            if (mDocumentUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)
+                    || mDocumentUri.getScheme().equals(ContentResolver.SCHEME_ANDROID_RESOURCE)) {
                 final boolean isReadOnlyDoc;
                 if (getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY) != null) {
                     // New document type string is not null, meaning we want to open a new document
@@ -296,53 +297,37 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
 
         try {
             mTempFile = File.createTempFile("LibreOffice", suffix, this.getCacheDir());
-            final FileChannel outputChannel = new FileOutputStream(mTempFile).getChannel();
-            try {
-                // need to run copy operation in a separate thread, since network access is not
-                // allowed from main thread, but that may happen here when underlying
-                // DocumentsProvider (like the NextCloud one) does that
-                class CopyThread extends Thread {
-                    /** Whether copy operation was successful. */
-                    private boolean result = false;
-
-                    @Override
-                    public void run() {
-                        result = false;
-                        try {
-                            final AssetFileDescriptor assetFD = contentResolver.openAssetFileDescriptor(mDocumentUri, "r");
-                            if (assetFD == null) {
-                                Log.e(LOGTAG, "couldn't create assetfiledescriptor from " + mDocumentUri);
-                                return;
-                            }
-                            FileChannel inputChannel = assetFD.createInputStream().getChannel();
-                            long bytesTransferred = 0;
-                            // might not  copy all at once, so make sure everything gets copied...
-                            while (bytesTransferred < inputChannel.size()) {
-                                bytesTransferred += outputChannel.transferFrom(inputChannel, bytesTransferred, inputChannel.size());
-                            }
-                            Log.e(LOGTAG, "Success copying " + bytesTransferred + " bytes");
-                            inputChannel.close();
-                        } catch (IOException e) {
-                            e.printStackTrace();
-                            return;
-                        }
-                        result = true;
+            final FileOutputStream outputStream = new FileOutputStream(mTempFile);
+            // need to run copy operation in a separate thread, since network access is not
+            // allowed from main thread, but that may happen here when underlying
+            // DocumentsProvider (like the NextCloud one) does that
+            class CopyThread extends Thread {
+                /** Whether copy operation was successful. */
+                private boolean result = false;
+
+                @Override
+                public void run() {
+                    result = false;
+                    try {
+                        InputStream inputStream = contentResolver.openInputStream(mDocumentUri);
+                        result = copyStream(inputStream, outputStream);
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                        return;
                     }
-                };
-                CopyThread copyThread = new CopyThread();
-                copyThread.start();
-                try {
-                    // wait for copy operation to finish
-                    // NOTE: might be useful to add some indicator in UI for long copy operations involving network...
-                    copyThread.join();
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
                 }
-
-                return copyThread.result;
-            } finally {
-                outputChannel.close();
+            };
+            CopyThread copyThread = new CopyThread();
+            copyThread.start();
+            try {
+                // wait for copy operation to finish
+                // NOTE: might be useful to add some indicator in UI for long copy operations involving network...
+                copyThread.join();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
             }
+
+            return copyThread.result;
         } catch (FileNotFoundException e) {
             return false;
         } catch (IOException e) {
commit b80deaefedfc9ac4fcaa14a8d350ebaa14d78a87
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 10:03:06 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:33:11 2021 +0200

    android: Drop fallback of opening default doc
    
    Drop the fallback of opening 'example.odt' when
    no file to open was given.
    I see no valid way how that fallback should be
    reached, so write an error log message instead,
    just in case there is still a way to get there.
    
    Change-Id: I8b8040ba0099cba9196f65982f09c67791be01c2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113880
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit bcb74b50920a44729ba2c88db98738a61d8d9920)

diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 2f067b48f90b..022965e65052 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -60,7 +60,6 @@ import java.util.UUID;
 public class LibreOfficeMainActivity extends AppCompatActivity implements SettingsListenerModel.OnSettingsPreferenceChangedListener {
 
     private static final String LOGTAG = "LibreOfficeMainActivity";
-    private static final String DEFAULT_DOC_PATH = "/assets/example.odt";
     private static final String ENABLE_EXPERIMENTAL_PREFS_KEY = "ENABLE_EXPERIMENTAL";
     private static final String ASSETS_EXTRACTED_PREFS_KEY = "ASSETS_EXTRACTED";
     private static final String ENABLE_DEVELOPER_PREFS_KEY = "ENABLE_DEVELOPER";
@@ -211,9 +210,8 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
                 toolbarTop.setTitle(mInputFile.getName());
             }
         } else {
-            mInputFile = new File(DEFAULT_DOC_PATH);
-            mDocumentUri = Uri.fromFile(mInputFile);
-            mbISReadOnlyMode = true;
+            Log.e(LOGTAG, "No document specified. This should never happen.");
+            return;
         }
 
         mDrawerLayout = findViewById(R.id.drawer_layout);
@@ -356,10 +354,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
      * Save the document.
      */
     public void saveDocument() {
-        if (!mInputFile.exists()) {
-            // Needed for handling null in case new document is not created.
-            mInputFile = new File(DEFAULT_DOC_PATH);
-        }
         Toast.makeText(this, R.string.message_saving, Toast.LENGTH_SHORT).show();
         // local save
         LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND_NOTIFY, ".uno:Save", true));
commit 08b94cc0cb0b1681d432745fabdbbc4c7d136979
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 10:00:48 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:33:02 2021 +0200

    android: Extract method to copy stream
    
    Extract method 'copyStream' used to copy the
    temporary file to the actual document URI when
    saving.
    It will also be used for copying the other way around
    when initially opening the document.
    
    Change-Id: I5382f4a7c49b454ff38fb8f95afab3c39145c11f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113879
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit 224df2980f0626b1e0b7f40c14348771ffff58fe)

diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 2a391dab4c8d..2f067b48f90b 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -44,6 +44,7 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
@@ -368,21 +369,15 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         if (isReadOnlyMode() || mInputFile == null || mDocumentUri == null || !mDocumentUri.getScheme().equals(ContentResolver.SCHEME_CONTENT))
             return;
 
-        FileInputStream inputStream = null;
-        OutputStream outputStream = null;
-
+        boolean copyOK = false;
         try {
-            inputStream = new FileInputStream(mInputFile);
-            // OutputStream for the actual (original) location
-            outputStream = getContentResolver().openOutputStream(mDocumentUri);
-
-            byte[] buffer = new byte[4096];
-            int readBytes = inputStream.read(buffer);
-            while (readBytes != -1) {
-                outputStream.write(buffer, 0, readBytes);
-                readBytes = inputStream.read(buffer);
-            }
-
+            final FileInputStream inputStream = new FileInputStream(mInputFile);
+            final OutputStream outputStream = getContentResolver().openOutputStream(mDocumentUri);
+            copyOK = copyStream(inputStream, outputStream);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        if (copyOK) {
             runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
@@ -391,7 +386,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
                 }
             });
             setDocumentChanged(false);
-        } catch (Exception e) {
+        } else {
             runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
@@ -399,16 +394,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
                         Toast.LENGTH_SHORT).show();
                 }
             });
-            e.printStackTrace();
-        } finally {
-            try {
-                if (inputStream != null)
-                    inputStream.close();
-                if (outputStream != null)
-                    outputStream.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
         }
     }
 
@@ -946,6 +931,33 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         }
     }
 
+    /**
+     * Copies everything from the given input stream to the given output stream
+     * and closes both streams in the end.
+     * @return Whether copy operation was successful.
+     */
+    private boolean copyStream(InputStream inputStream, OutputStream outputStream) {
+        try {
+            byte[] buffer = new byte[4096];
+            int readBytes = inputStream.read(buffer);
+            while (readBytes != -1) {
+                outputStream.write(buffer, 0, readBytes);
+                readBytes = inputStream.read(buffer);
+            }
+            return true;
+        } catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        } finally {
+            try {
+                inputStream.close();
+                outputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
     public void showCustomStatusMessage(String message){
         Snackbar.make(mDrawerLayout, message, Snackbar.LENGTH_LONG).show();
     }
@@ -990,7 +1002,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
     }
-
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 824a5350afc229fcc7d0672b1f660115d31d8736
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Thu Apr 8 14:06:05 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:32:54 2021 +0200

    android: Add member for document URI
    
    Add a 'mDocumentUri' member in LibreOfficeMainActivity
    to store the document URI rather than retrieving it from
    the Intent using 'getIntent().getData()' all the time.
    
    This is also in preparation to make it possible to change
    the URI later, e.g. when doing a "Save As".
    
    While at it, also switch to readonly mode for the
    fallback to 'DEFAULT_DOC_PATH' (though I don't think
    this should be relevant anyway).
    
    Change-Id: I629bad1d743e458191dcfa2b1371ea4b280e7b13
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113878
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit 79d9a7349174a7e2b2aa7fcf324a6987edbbd555)

diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 6af44912bb52..2a391dab4c8d 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -82,6 +82,9 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     private int partIndex=-1;
     private File mInputFile;
     private DocumentOverlay mDocumentOverlay;
+    /** URI of the actual document. */
+    private Uri mDocumentUri;
+    /** Temporary local copy of the document. */
     private File mTempFile = null;
     private File mTempSlideShowFile = null;
     public boolean firstStart = true;
@@ -170,8 +173,9 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
 
         mbISReadOnlyMode = !isExperimentalMode();
 
-        if (getIntent().getData() != null) {
-            if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
+        mDocumentUri = getIntent().getData();
+        if (mDocumentUri != null) {
+            if (mDocumentUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
                 final boolean isReadOnlyDoc;
                 if (getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY) != null) {
                     // New document type string is not null, meaning we want to open a new document
@@ -185,28 +189,30 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
                     isReadOnlyDoc = (getIntent().getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
                 } else {
                     // TODO: can't open the file
-                    Log.e(LOGTAG, "couldn't create temporary file from " + getIntent().getData());
+                    Log.e(LOGTAG, "couldn't create temporary file from " + mDocumentUri);
                     return;
                 }
 
-                mbISReadOnlyMode = !isExperimentalMode()  || isReadOnlyDoc;
-                Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath());
+                mbISReadOnlyMode = !isExperimentalMode() || isReadOnlyDoc;
+                Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + mDocumentUri.getPath());
 
-                String displayName = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), getIntent().getData());
+                String displayName = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), mDocumentUri);
                 if (displayName.isEmpty()) {
                     // fall back to using temp file name
                     displayName = mInputFile.getName();
                 }
                 toolbarTop.setTitle(displayName);
 
-            } else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) {
-                mInputFile = new File(getIntent().getData().getPath());
+            } else if (mDocumentUri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
+                mInputFile = new File(mDocumentUri.getPath());
                 mbISReadOnlyMode = true;
-                Log.d(LOGTAG, "SCHEME_FILE: getPath(): " + getIntent().getData().getPath());
+                Log.d(LOGTAG, "SCHEME_FILE: getPath(): " + mDocumentUri.getPath());
                 toolbarTop.setTitle(mInputFile.getName());
             }
         } else {
             mInputFile = new File(DEFAULT_DOC_PATH);
+            mDocumentUri = Uri.fromFile(mInputFile);
+            mbISReadOnlyMode = true;
         }
 
         mDrawerLayout = findViewById(R.id.drawer_layout);
@@ -304,9 +310,9 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
                     public void run() {
                         result = false;
                         try {
-                            final AssetFileDescriptor assetFD = contentResolver.openAssetFileDescriptor(getIntent().getData(), "r");
+                            final AssetFileDescriptor assetFD = contentResolver.openAssetFileDescriptor(mDocumentUri, "r");
                             if (assetFD == null) {
-                                Log.e(LOGTAG, "couldn't create assetfiledescriptor from " + getIntent().getDataString());
+                                Log.e(LOGTAG, "couldn't create assetfiledescriptor from " + mDocumentUri);
                                 return;
                             }
                             FileChannel inputChannel = assetFD.createInputStream().getChannel();
@@ -359,17 +365,16 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     }
 
     public void saveFileToOriginalSource() {
-        if (isReadOnlyMode() || mInputFile == null || getIntent().getData() == null || !getIntent().getData().getScheme().equals(ContentResolver.SCHEME_CONTENT))
+        if (isReadOnlyMode() || mInputFile == null || mDocumentUri == null || !mDocumentUri.getScheme().equals(ContentResolver.SCHEME_CONTENT))
             return;
 
-        Uri uri = getIntent().getData();
         FileInputStream inputStream = null;
         OutputStream outputStream = null;
 
         try {
             inputStream = new FileInputStream(mInputFile);
             // OutputStream for the actual (original) location
-            outputStream = getContentResolver().openOutputStream(uri);
+            outputStream = getContentResolver().openOutputStream(mDocumentUri);
 
             byte[] buffer = new byte[4096];
             int readBytes = inputStream.read(buffer);
commit 6ee0cecf5c54faff6bd2679256f32373c11a2e2a
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 12:50:22 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:32:44 2021 +0200

    android: Check result for CREATE_NEW_DOCUMENT Intent
    
    Only try to retrieve the file URI and load the document
    if a file was actually selected.
    
    Change-Id: Icd47c197b67d593e74874e8136233b6e41a1a68d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113845
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit d214ab444e73490f4c95dffd7f376978cbcd3ccc)

diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
index e7bb998bb826..9f1cd7a9089d 100644
--- a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
+++ b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
@@ -257,7 +257,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
         if (requestCode == REQUEST_CODE_OPEN_FILECHOOSER && resultCode == RESULT_OK) {
             final Uri fileUri = data.getData();
             openDocument(fileUri);
-        } else if (requestCode == REQUEST_CODE_CREATE_NEW_DOCUMENT) {
+        } else if (requestCode == REQUEST_CODE_CREATE_NEW_DOCUMENT && resultCode == RESULT_OK) {
             // "forward" to LibreOfficeMainActivity to create + open the file
             final Uri fileUri = data.getData();
             loadNewDocument(newDocType, fileUri);
commit deeb5854c0eba2d81a5dce6be8b8fcb56fa968b5
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Fri Apr 9 11:24:16 2021 +0200
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Mon Apr 12 07:32:27 2021 +0200

    android: Request PERMISSION_WRITE_EXTERNAL_STORAGE again
    
    Requesting the permission on app start had been dropped in
    
        commit a23bd42e9b2f6401c710ac95afcc3aa8f360d65c
        Date:   Tue Apr 6 14:26:06 2021 +0200
    
            android: Drop custom file abstraction + UI
    
    Since the app now uses the Android Storage Access Framework [1]
    in order to open or create files from within the app,
    it not longer needs PERMISSION_WRITE_EXTERNAL_STORAGE for this.
    However, at least PDF export currently still directly writes
    to local storage ("Documents" directory), which fails without
    that permission being granted.
    
    In addition, opening files passed with a 'file://' URI
    in an 'Intent.ACTION_VIEW' also did not work anymore.
    I'm not sure whether this use case is particularly
    relevant in practice, though; at least all of the (few)
    apps I used during testing passed 'content://' URIs in their
    Intent.
    
    In addition, in Android 11 (API level 30) or higher,
    PERMISSION_WRITE_EXTERNAL_STORAGE no longer has any effect;
    from [2]:
    
    > More recent versions of Android rely more on a file's purpose than its
    > location for determining an app's ability to access, and write to, a
    > given file. In particular, if your app targets Android 11 (API level 30)
    > or higher, the WRITE_EXTERNAL_STORAGE permission doesn't have any
    > effect on your app's access to storage. This purpose-based storage
    > model improves user privacy because apps are given access only to
    > the areas of the device's file system that they actually use.
    >
    > Android 11 introduces the MANAGE_EXTERNAL_STORAGE permission, which
    > provides write access to files outside the app-specific directory and
    > MediaStore. To learn more about this permission, and why most apps don't
    > need to declare it to fulfill their use cases, see the guide on how to
    > manage all files [3] on a storage device.
    
    For now, request the permission again, at least as long
    as PDF export doesn't use the storage framework to
    ask where to save files.
    It certainly makes sense to reconsider this in the future (and decide to either
    drop the permission completely or request MANAGE_EXTERNAL_STORAGE for API
    level >=30).
    
    [1] https://developer.android.com/training/data-storage/shared/documents-files
    [2] https://developer.android.com/training/data-storage#permissions
    [3] https://developer.android.com/training/data-storage/manage-all-files
    
    Change-Id: Icc4c9c9b7b315d2a0b6a025439ae7e431cdd5b37
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113840
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit 7d9db806d65cb814af1e99a1e79c3db5aa7c17d5)

diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
index 9f89bbedc525..e7bb998bb826 100644
--- a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
+++ b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
@@ -9,11 +9,13 @@
 
 package org.libreoffice.ui;
 
+import android.Manifest;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.graphics.drawable.Icon;
@@ -21,7 +23,10 @@ import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
+import android.support.annotation.NonNull;
 import android.support.design.widget.FloatingActionButton;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.AppCompatActivity;
@@ -120,6 +125,8 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
     private static final int REQUEST_CODE_OPEN_FILECHOOSER = 12345;
     private static final int REQUEST_CODE_CREATE_NEW_DOCUMENT = 12346;
 
+    private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
+
     private Animation fabOpenAnimation;
     private Animation fabCloseAnimation;
     private boolean isFabMenuOpen = false;
@@ -146,6 +153,17 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
         fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close);
     }
 
+    @Override
+    protected void onStart() {
+        super.onStart();
+        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
+            Log.i(LOGTAG, "no permission to read external storage - asking for permission");
+            ActivityCompat.requestPermissions(this,
+                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+                PERMISSION_WRITE_EXTERNAL_STORAGE);
+        }
+    }
+
     @Override
     protected void attachBaseContext(Context newBase) {
         super.attachBaseContext(LocaleHelper.onAttach(newBase));


More information about the Libreoffice-commits mailing list