[Libreoffice-commits] online.git: android/app android/.gitignore android/lib android/Makefile.am android/settings.gradle configure.ac .gitignore loleaflet/Makefile.am

Jan Holesovsky (via logerrit) logerrit at kemper.freedesktop.org
Fri Jul 12 09:54:18 UTC 2019


 .gitignore                                                                         |    6 
 android/.gitignore                                                                 |   20 
 android/Makefile.am                                                                |   12 
 android/app/.gitignore                                                             |    2 
 android/app/appSettings.gradle.in                                                  |   12 
 android/app/build.gradle                                                           |  172 ---
 android/app/src/main/java/org/libreoffice/androidapp/MainActivity.java             |  503 ---------
 android/app/src/main/java/org/libreoffice/androidapp/ui/LibreOfficeUIActivity.java |    4 
 android/lib/.gitignore                                                             |    3 
 android/lib/build.gradle                                                           |  210 ++++
 android/lib/libSettings.gradle.in                                                  |   11 
 android/lib/proguard-rules.pro                                                     |   21 
 android/lib/src/main/AndroidManifest.xml                                           |    2 
 android/lib/src/main/cpp/androidapp.cpp                                            |   20 
 android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java               |  515 ++++++++++
 android/lib/src/main/java/org/libreoffice/androidlib/PrintAdapter.java             |    6 
 android/lib/src/main/java/org/libreoffice/androidlib/SlideShowActivity.java        |    2 
 android/lib/src/main/res/layout/activity_main.xml                                  |    2 
 android/lib/src/main/res/values/strings.xml                                        |    8 
 android/settings.gradle                                                            |    2 
 configure.ac                                                                       |    5 
 loleaflet/Makefile.am                                                              |   12 
 22 files changed, 821 insertions(+), 729 deletions(-)

New commits:
commit 2b13c69d75476bcc3a38bd0cd9798187e74ed4c4
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Thu Jul 11 11:29:13 2019 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Jul 12 11:52:56 2019 +0200

    android: Split the actual editing Activity into an own library.
    
    This way, it is more naturally visible what is the actuall app (with the
    initial recent documents / file picker) and the editing part.
    
    Change-Id: Ia764f2900939e980f703e3da9f9abd6c0aee7cbb

diff --git a/.gitignore b/.gitignore
index 52ee34543..eea283edd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,9 +95,9 @@ ios/Mobile/Assets.xcassets/AppIcon.appiconset
 BUNDLE-VERSION
 
 # android stuff
-/android/app/src/main/assets/dist
-/android/app/src/main/assets/hello-world.od*
-/android/app/src/main/cpp/CMakeLists.txt
+/android/lib/src/main/assets/dist
+/android/lib/src/main/assets/hello-world.od*
+/android/lib/src/main/cpp/CMakeLists.txt
 
 # backup and temporary editor files: the only convenience rules allowed here.
 *~
diff --git a/android/.gitignore b/android/.gitignore
index 6e50fa55a..9bdedd758 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -3,13 +3,13 @@
 /android.iml
 /gradle
 /local.properties
-/app/src/main/assets/etc/
-/app/src/main/assets/example.odt
-/app/src/main/assets/license.txt
-/app/src/main/assets/license.html
-/app/src/main/assets/notice.txt
-/app/src/main/assets/program/
-/app/src/main/assets/share/
-/app/src/main/assets/unpack/
-/app/src/main/assets/user/
-/app/src/main/cpp/lib
+/lib/src/main/assets/etc/
+/lib/src/main/assets/example.odt
+/lib/src/main/assets/license.txt
+/lib/src/main/assets/license.html
+/lib/src/main/assets/notice.txt
+/lib/src/main/assets/program/
+/lib/src/main/assets/share/
+/lib/src/main/assets/unpack/
+/lib/src/main/assets/user/
+/lib/src/main/cpp/lib
diff --git a/android/Makefile.am b/android/Makefile.am
index 9d27873df..fb3076a46 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -1,12 +1,12 @@
 clean-local:
-	rm -rf $(abs_top_srcdir)/android/app/src/main/assets/*
+	rm -rf $(abs_top_srcdir)/android/lib/src/main/assets/*
 	rm -rf app/build
 
-all-local: app/src/main/assets/templates/untitled.odg \
-	   app/src/main/assets/templates/untitled.odp \
-	   app/src/main/assets/templates/untitled.ods \
-	   app/src/main/assets/templates/untitled.odt
+all-local: lib/src/main/assets/templates/untitled.odg \
+	   lib/src/main/assets/templates/untitled.odp \
+	   lib/src/main/assets/templates/untitled.ods \
+	   lib/src/main/assets/templates/untitled.odt
 
-app/src/main/assets/templates/untitled.%: templates/untitled.%
+lib/src/main/assets/templates/untitled.%: templates/untitled.%
 	@mkdir -p $(dir $@)
 	@cp -a $< $@
diff --git a/android/app/.gitignore b/android/app/.gitignore
index 238a7c9a1..0e5159da5 100644
--- a/android/app/.gitignore
+++ b/android/app/.gitignore
@@ -1,4 +1,4 @@
 /.externalNativeBuild
 /app.iml
 /build
-/liboSettings.gradle
+/appSettings.gradle
diff --git a/android/app/appSettings.gradle.in b/android/app/appSettings.gradle.in
new file mode 100644
index 000000000..d872ef2ea
--- /dev/null
+++ b/android/app/appSettings.gradle.in
@@ -0,0 +1,12 @@
+ext {
+    liboWorkdir         = '@LOBUILDDIR@/workdir'
+    liboVersionMinor    = '@LOOLWSD_VERSION_MAJOR@'
+    liboAppName         = '@APP_NAME@'
+    liboVendor          = '@VENDOR@'
+    liboInfoURL         = '@INFO_URL@'
+}
+android.defaultConfig {
+    applicationId '@ANDROID_PACKAGE_NAME@'
+    versionCode 20
+    versionName '@LOOLWSD_VERSION@'
+}
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 0ee8baabe..aae9c4bc0 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,12 +1,12 @@
 apply plugin: 'com.android.application'
 
 // buildhost settings - paths and the like
-apply from: 'liboSettings.gradle'
+apply from: 'appSettings.gradle'
 
 android {
     compileSdkVersion 28
     defaultConfig {
-        // applicationId, versionCode and versionName are defined in liboSettings.gradle
+        // applicationId, versionCode and versionName are defined in appSettings.gradle
         minSdkVersion 21
         targetSdkVersion 28
     }
@@ -36,17 +36,6 @@ android {
                     'proguard-rules.pro'
         }
     }
-    sourceSets {
-        main {
-            // let gradle pack the shared library into apk
-            jniLibs.srcDirs = ['src/main/cpp/lib']
-        }
-    }
-    externalNativeBuild {
-        cmake {
-            path "src/main/cpp/CMakeLists.txt"
-        }
-    }
 }
 
 repositories {
@@ -65,160 +54,5 @@ dependencies {
 
     //before changing the version please see https://issuetracker.google.com/issues/111662669
     implementation 'androidx.preference:preference:1.1.0-alpha01'
+    implementation project(path: ':lib')
 }
-
-task copyUnpackAssets(type: Copy) {
-    description "copies assets that need to be extracted on the device"
-    into 'src/main/assets/unpack'
-    into('program') {
-        from("${liboInstdir}/${liboEtcFolder}/types") {
-            includes = [
-                    "offapi.rdb",
-                    "oovbaapi.rdb"
-            ]
-        }
-        from("${liboInstdir}/${liboUreMiscFolder}") {
-            includes = ["types.rdb"]
-            rename 'types.rdb', 'udkapi.rdb'
-        }
-    }
-    into('user/fonts') {
-        from "${liboInstdir}/share/fonts/truetype"
-        // Note: restrict list of fonts due to size considerations - no technical reason anymore
-        // ToDo: fonts would be good candidate for using Expansion Files instead
-        includes = [
-                "Liberation*.ttf",
-                "Caladea-*.ttf",
-                "Carlito-*.ttf",
-                "Gen*.ttf",
-                "opens___.ttf"
-        ]
-    }
-    into('etc/fonts') {
-        from "${liboSrcRoot}/android/source/"
-        includes = ['fonts.conf']
-        filter {
-            String line ->
-                line.replaceAll(
-                    '@@APPLICATION_ID@@', new String("${android.defaultConfig.applicationId}")
-                ).replaceAll(
-                    // FIXME Avoid the Android system fonts for the moment,
-                    // the huge Noto Sans fonts have terrible impact on the 1st
-                    // start performance.
-                    // The real solution would be to either make fontconfig
-                    // faster, or at least find a way to avoid only the Noto
-                    // Sans, or present a progressbar or something.
-                    // For the moment, we just copy the Roboto font (needed
-                    // for the dialogs; see MainActivity.copyFonts()) and
-                    // remove the system fonts from the config.
-                    '<dir>/system/fonts</dir>', new String("")
-                )
-        }
-    }
-}
-
-task copyAssets(type: Copy) {
-    description "copies assets that can be accessed within the installed apk"
-    into 'src/main/assets'
-    from("${liboSrcRoot}/instdir/") {
-        includes = ["LICENSE.html", "NOTICE"]
-        rename "LICENSE.html", "license.html"
-        rename "NOTICE", "notice.txt"
-    }
-    from("${liboExampleDocument}") {
-        rename ".*", "example.odt"
-    }
-    into('program') {
-        from "${liboInstdir}/program"
-        includes = ['services.rdb', 'services/services.rdb']
-
-        into('resource') {
-            from "${liboInstdir}/${liboSharedResFolder}"
-            includes = ['*en-US.res']
-        }
-    }
-    into('share') {
-        from "${liboInstdir}/share"
-        // Filter data is needed by e.g. the drawingML preset shape import.
-        includes = ['registry/**', 'filter/**']
-    }
-}
-
-task createFullConfig(type: Copy) {
-    description "copies various configuration bits into the apk"
-    into('src/main/assets/share/config')
-    from("${liboInstdir}/share/config") {
-        includes = ['soffice.cfg/**', 'images_colibre.zip']
-    }
-}
-
-task createStrippedConfig {
-    def preserveDir = file("src/main/assets/share/config/soffice.cfg/empty")
-    outputs.dir "src/main/assets/share/registry/res"
-    outputs.file preserveDir
-
-    doLast {
-        file('src/main/assets/share/registry/res').mkdirs()
-        file("src/main/assets/share/config/soffice.cfg").mkdirs()
-        // just empty file
-        preserveDir.text = ""
-    }
-}
-
-task createRCfiles {
-    inputs.file "liboSettings.gradle"
-    dependsOn copyUnpackAssets, copyAssets
-    def sofficerc = file('src/main/assets/unpack/program/sofficerc')
-    def fundamentalrc = file('src/main/assets/program/fundamentalrc')
-    def bootstraprc = file('src/main/assets/program/bootstraprc')
-    def unorc = file('src/main/assets/program/unorc')
-    def versionrc = file('src/main/assets/program/versionrc')
-
-    outputs.files sofficerc, fundamentalrc, unorc, bootstraprc, versionrc
-
-    doLast {
-        sofficerc.text = '''\
-[Bootstrap]
-Logo=1
-NativeProgress=1
-URE_BOOTSTRAP=file:///assets/program/fundamentalrc
-HOME=$APP_DATA_DIR/cache
-OSL_SOCKET_PATH=$APP_DATA_DIR/cache
-'''.stripIndent()
-
-        fundamentalrc.text = '''\
-[Bootstrap]
-LO_LIB_DIR=file://$APP_DATA_DIR/lib/
-BRAND_BASE_DIR=file:///assets
-BRAND_SHARE_SUBDIR=share
-CONFIGURATION_LAYERS=xcsxcu:${BRAND_BASE_DIR}/share/registry res:${BRAND_BASE_DIR}/share/registry
-URE_BIN_DIR=file:///assets/ure/bin/dir/nothing-here/we-can/exec-anyway
-'''.stripIndent()
-
-        bootstraprc.text = '''\
-[Bootstrap]
-InstallMode=<installmode>
-ProductKey=LibreOffice ''' + "${liboVersionMajor}.${liboVersionMinor}" + '''
-UserInstallation=file://$APP_DATA_DIR
-'''.stripIndent()
-
-        unorc.text = '''\
-[Bootstrap]
-URE_INTERNAL_LIB_DIR=file://$APP_DATA_DIR/lib/
-UNO_TYPES=file://$APP_DATA_DIR/program/udkapi.rdb file://$APP_DATA_DIR/program/offapi.rdb file://$APP_DATA_DIR/program/oovbaapi.rdb
-UNO_SERVICES=file:///assets/program/services.rdb file:///assets/program/services/services.rdb
-'''.stripIndent()
-
-        versionrc.text = '''\
-[Version]
-AllLanguages=en-US
-BuildVersion=
-buildid=''' + "${liboGitFullCommit}" + '''
-ReferenceOOoMajorMinor=4.1
-'''.stripIndent()
-    }
-}
-
-// creating the UI stuff is cheap, don't bother only applying it for the flavor..
-preBuild.dependsOn 'createRCfiles',
-        'createFullConfig'
diff --git a/android/app/src/main/java/org/libreoffice/androidapp/MainActivity.java b/android/app/src/main/java/org/libreoffice/androidapp/MainActivity.java
index c2897e304..4c75b27c4 100644
--- a/android/app/src/main/java/org/libreoffice/androidapp/MainActivity.java
+++ b/android/app/src/main/java/org/libreoffice/androidapp/MainActivity.java
@@ -9,508 +9,9 @@
 
 package org.libreoffice.androidapp;
 
-import android.Manifest;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.AssetManager;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.Handler;
-import android.preference.PreferenceManager;
-import android.print.PrintAttributes;
-import android.print.PrintDocumentAdapter;
-import android.print.PrintManager;
-import android.util.Log;
-import android.webkit.JavascriptInterface;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.Toast;
-
-import java.io.File;
-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.net.URI;
-import java.net.URISyntaxException;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
-
-public class MainActivity extends AppCompatActivity {
-    final static String TAG = "MainActivity";
-
-    private static final String ASSETS_EXTRACTED_PREFS_KEY = "ASSETS_EXTRACTED";
-    private static final int PERMISSION_READ_EXTERNAL_STORAGE = 777;
-    private static final String KEY_ENABLE_SHOW_DEBUG_INFO = "ENABLE_SHOW_DEBUG_INFO";
-
-    private static final String KEY_PROVIDER_ID = "providerID";
-    private static final String KEY_DOCUMENT_URI = "documentUri";
-    private static final String KEY_IS_EDITABLE = "isEditable";
-    private static final String KEY_INTENT_URI = "intentUri";
-
-    private File mTempFile = null;
-
-    private int providerId;
-
-    @Nullable
-    private URI documentUri;
-
-    private String urlToLoad;
-    private WebView mWebView;
-    private SharedPreferences sPrefs;
-    private Handler mainHandler;
-
-    private boolean isDocEditable = false;
-    private boolean isDocDebuggable = BuildConfig.DEBUG;
-
-    private static boolean copyFromAssets(AssetManager assetManager,
-                                          String fromAssetPath, String targetDir) {
-        try {
-            String[] files = assetManager.list(fromAssetPath);
-
-            boolean res = true;
-            for (String file : files) {
-                String[] dirOrFile = assetManager.list(fromAssetPath + "/" + file);
-                if (dirOrFile.length == 0) {
-                    // noinspection ResultOfMethodCallIgnored
-                    new File(targetDir).mkdirs();
-                    res &= copyAsset(assetManager,
-                            fromAssetPath + "/" + file,
-                            targetDir + "/" + file);
-                } else
-                    res &= copyFromAssets(assetManager,
-                            fromAssetPath + "/" + file,
-                            targetDir + "/" + file);
-            }
-            return res;
-        } catch (Exception e) {
-            e.printStackTrace();
-            Log.e(TAG, "copyFromAssets failed: " + e.getMessage());
-            return false;
-        }
-    }
-
-    private static boolean copyAsset(AssetManager assetManager, String fromAssetPath, String toPath) {
-        ReadableByteChannel source = null;
-        FileChannel dest = null;
-        try {
-            try {
-                source = Channels.newChannel(assetManager.open(fromAssetPath));
-                dest = new FileOutputStream(toPath).getChannel();
-                long bytesTransferred = 0;
-                // might not copy all at once, so make sure everything gets copied....
-                ByteBuffer buffer = ByteBuffer.allocate(4096);
-                while (source.read(buffer) > 0) {
-                    buffer.flip();
-                    bytesTransferred += dest.write(buffer);
-                    buffer.clear();
-                }
-                Log.v(TAG, "Success copying " + fromAssetPath + " to " + toPath + " bytes: " + bytesTransferred);
-                return true;
-            } finally {
-                if (dest != null) dest.close();
-                if (source != null) source.close();
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "file " + fromAssetPath + " not found! " + e.getMessage());
-            return false;
-        } catch (IOException e) {
-            Log.e(TAG, "failed to copy file " + fromAssetPath + " from assets to " + toPath + " - " + e.getMessage());
-            return false;
-        }
-    }
-
-    /** Copies fonts except the NotoSans from the system to our location.
-     *  This is necessary because the NotoSans is huge and fontconfig needs
-     *  ages to parse them.
-     */
-    private static boolean copyFonts(String fromPath, String targetDir) {
-        try {
-            File target = new File(targetDir);
-            if (!target.exists())
-                target.mkdirs();
-
-            File from = new File(fromPath);
-            File[] files = from.listFiles();
-            for (File fontFile : files) {
-                String fontFileName = fontFile.getName();
-                if (!fontFileName.equals("Roboto-Regular.ttf")) {
-                    Log.i(TAG, "Ignored font file: " + fontFile);
-                    continue;
-                }
-                else {
-                    Log.i(TAG, "Copying font file: " + fontFile);
-                }
-
-                // copy the font file over
-                InputStream in = new FileInputStream(fontFile);
-                try {
-                    OutputStream out = new FileOutputStream(targetDir + "/" + fontFile.getName());
-                    try {
-                        byte[] buffer = new byte[4096];
-                        int len;
-                        while ((len = in.read(buffer)) > 0) {
-                            out.write(buffer, 0, len);
-                        }
-                    } finally {
-                        out.close();
-                    }
-                } finally {
-                    in.close();
-                }
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            Log.e(TAG, "copyFonts failed: " + e.getMessage());
-            return false;
-        }
-
-        return true;
-    }
-
-    private void updatePreferences() {
-        if (sPrefs.getInt(ASSETS_EXTRACTED_PREFS_KEY, 0) != BuildConfig.VERSION_CODE) {
-            if (copyFromAssets(getAssets(), "unpack", getApplicationInfo().dataDir) &&
-                    copyFonts("/system/fonts", getApplicationInfo().dataDir + "/user/fonts")) {
-                sPrefs.edit().putInt(ASSETS_EXTRACTED_PREFS_KEY, BuildConfig.VERSION_CODE).apply();
-            }
-        }
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        sPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
-        updatePreferences();
-
-        setContentView(R.layout.activity_main);
-
-        AssetManager assetManager = getResources().getAssets();
-
-        isDocDebuggable = sPrefs.getBoolean(KEY_ENABLE_SHOW_DEBUG_INFO, false) && BuildConfig.DEBUG;
-
-        ApplicationInfo applicationInfo = getApplicationInfo();
-        String dataDir = applicationInfo.dataDir;
-        Log.i(TAG, String.format("Initializing LibreOfficeKit, dataDir=%s\n", dataDir));
-
-        //redirectStdio(true);
-
-        String cacheDir = getApplication().getCacheDir().getAbsolutePath();
-        String apkFile = getApplication().getPackageResourcePath();
-
-        if (getIntent().getData() != null) {
-
-            if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
-                isDocEditable = false;
-                Toast.makeText(this, getResources().getString(R.string.temp_file_saving_disabled), Toast.LENGTH_SHORT).show();
-                if (copyFileToTemp() && mTempFile != null) {
-                    documentUri = mTempFile.toURI();
-                    urlToLoad = documentUri.toString();
-                    Log.d(TAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath());
-                } else {
-                    // TODO: can't open the file
-                    Log.e(TAG, "couldn't create temporary file from " + getIntent().getData());
-                }
-            } else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) {
-                isDocEditable = true;
-                urlToLoad = getIntent().getData().getPath();
-                Log.d(TAG, "SCHEME_FILE: getPath(): " + getIntent().getData().getPath());
-                // Gather data to rebuild IFile object later
-                providerId = getIntent().getIntExtra(
-                        "org.libreoffice.document_provider_id", 0);
-                documentUri = (URI) getIntent().getSerializableExtra(
-                        "org.libreoffice.document_uri");
-            }
-        } else if (savedInstanceState != null) {
-            getIntent().setAction(Intent.ACTION_VIEW)
-                    .setData(Uri.parse(savedInstanceState.getString(KEY_INTENT_URI)));
-            urlToLoad = getIntent().getData().toString();
-            providerId = savedInstanceState.getInt(KEY_PROVIDER_ID);
-            if (savedInstanceState.getString(KEY_DOCUMENT_URI) != null) {
-                try {
-                    documentUri = new URI(savedInstanceState.getString(KEY_DOCUMENT_URI));
-                    urlToLoad = documentUri.toString();
-                } catch (URISyntaxException e) {
-                    e.printStackTrace();
-                }
-            }
-            isDocEditable = savedInstanceState.getBoolean(KEY_IS_EDITABLE);
-        } else {
-            //User can't reach here but if he/she does then
-            Toast.makeText(this, getString(R.string.failed_to_load_file), Toast.LENGTH_SHORT).show();
-            finish();
-        }
-
-        createLOOLWSD(dataDir, cacheDir, apkFile, assetManager, urlToLoad);
-
-        mWebView = findViewById(R.id.browser);
-        mWebView.setWebViewClient(new WebViewClient());
-
-        WebSettings webSettings = mWebView.getSettings();
-        webSettings.setJavaScriptEnabled(true);
-        mWebView.addJavascriptInterface(this, "LOOLMessageHandler");
-
-        // allow debugging (when building the debug version); see details in
-        // https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
-                WebView.setWebContentsDebuggingEnabled(true);
-            }
-        }
-        mainHandler = new Handler(getMainLooper());
-    }
-
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
-            Log.i(TAG, "asking for read storage permission");
-            ActivityCompat.requestPermissions(this,
-                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
-                    PERMISSION_READ_EXTERNAL_STORAGE);
-        } else {
-            loadDocument();
-        }
-    }
-
-    @Override
-    protected void onSaveInstanceState(@NonNull Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putString(KEY_INTENT_URI, getIntent().getData().toString());
-        outState.putInt(KEY_PROVIDER_ID, providerId);
-        if (documentUri != null) {
-            outState.putString(KEY_DOCUMENT_URI, documentUri.toString());
-        }
-        //If this activity was opened via contentUri
-        outState.putBoolean(KEY_IS_EDITABLE, isDocEditable);
-    }
-
-    @Override
-    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
-        switch (requestCode) {
-            case PERMISSION_READ_EXTERNAL_STORAGE:
-                if (permissions.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-                    loadDocument();
-                } else {
-                    Toast.makeText(this, getString(R.string.storage_permission_required), Toast.LENGTH_SHORT).show();
-                    finish();
-                    break;
-                }
-                break;
-            default:
-                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
-        }
-    }
-
-    private boolean copyFileToTemp() {
-        ContentResolver contentResolver = getContentResolver();
-        FileChannel inputChannel = null;
-        FileChannel outputChannel = null;
-        // CSV files need a .csv suffix to be opened in Calc.
-        String suffix = null;
-        String intentType = getIntent().getType();
-        // K-9 mail uses the first, GMail uses the second variant.
-        if ("text/comma-separated-values".equals(intentType) || "text/csv".equals(intentType))
-            suffix = ".csv";
-
-        try {
-            try {
-                AssetFileDescriptor assetFD = contentResolver.openAssetFileDescriptor(getIntent().getData(), "r");
-                if (assetFD == null) {
-                    Log.e(TAG, "couldn't create assetfiledescriptor from " + getIntent().getDataString());
-                    return false;
-                }
-                inputChannel = assetFD.createInputStream().getChannel();
-                mTempFile = File.createTempFile("LibreOffice", suffix, this.getCacheDir());
-
-                outputChannel = new FileOutputStream(mTempFile).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(TAG, "Success copying " + bytesTransferred + " bytes");
-                return true;
-            } finally {
-                if (inputChannel != null) inputChannel.close();
-                if (outputChannel != null) outputChannel.close();
-            }
-        } catch (FileNotFoundException e) {
-            return false;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        Log.i(TAG, "onResume..");
-
-        // check for config change
-        updatePreferences();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        Log.d(TAG, "onPause() - unload the document");
-        postMobileMessageNative("BYE");
-    }
-
-    private void loadDocument() {
-        String finalUrlToLoad = "file:///android_asset/dist/loleaflet.html?file_path=" +
-                urlToLoad + "&closebutton=1";
-        if (isDocEditable) {
-            finalUrlToLoad += "&permission=edit";
-        } else {
-            finalUrlToLoad += "&permission=readonly";
-        }
-        if (isDocDebuggable) {
-            finalUrlToLoad += "&debug=true";
-        }
-        mWebView.loadUrl(finalUrlToLoad);
-    }
-
-    static {
-        System.loadLibrary("androidapp");
-    }
-
-    /**
-     * Initialize the LOOLWSD to load 'loadFileURL'.
-     */
-    public native void createLOOLWSD(String dataDir, String cacheDir, String apkFile, AssetManager assetManager, String loadFileURL);
-
-    /**
-     * Passing messages from JS (instead of the websocket communication).
-     */
-    @JavascriptInterface
-    public void postMobileMessage(String message) {
-        Log.d(TAG, "postMobileMessage: " + message);
-
-        if (interceptMsgFromWebView(message)) {
-            postMobileMessageNative(message);
-        }
-
-        // Going back to document browser on BYE (called when pressing the top left exit button)
-        if (message.equals("BYE"))
-            finish();
-    }
-
-    /**
-     * Call the post method form C++
-     */
-    public native void postMobileMessageNative(String message);
-
-    /**
-     * Passing messages from JS (instead of the websocket communication).
-     */
-    @JavascriptInterface
-    public void postMobileError(String message) {
-        // TODO handle this
-        Log.d(TAG, "postMobileError: " + message);
-    }
-
-    /**
-     * Passing messages from JS (instead of the websocket communication).
-     */
-    @JavascriptInterface
-    public void postMobileDebug(String message) {
-        // TODO handle this
-        Log.d(TAG, "postMobileDebug: " + message);
-    }
-
-    /**
-     * Passing message the other way around - from Java to the FakeWebSocket in JS.
-     */
-    void callFakeWebsocketOnMessage(final String message) {
-        // call from the UI thread
-        mWebView.post(new Runnable() {
-            public void run() {
-                Log.i(TAG, "Forwarding to the WebView: " + message);
-                mWebView.loadUrl("javascript:window.TheFakeWebSocket.onmessage({'data':" + message + "});");
-            }
-        });
-    }
-
-    /**
-     * return true to pass the message to the native part and false to block the message
-     */
-    boolean interceptMsgFromWebView(String message) {
-        if (message.equals("PRINT")) {
-            mainHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    initiatePrint();
-                }
-            });
-            return false;
-        } else if (message.equals("SLIDESHOW")) {
-            initiateSlideShow();
-            return false;
-        }
-        return true;
-    }
-
-    private void initiatePrint() {
-        PrintManager printManager = (PrintManager) getSystemService(PRINT_SERVICE);
-        PrintDocumentAdapter printAdapter = new PrintAdapter(MainActivity.this);
-        printManager.print("Document", printAdapter, new PrintAttributes.Builder().build());
-    }
-
-    private void initiateSlideShow() {
-        final AlertDialog slideShowProgress = new AlertDialog.Builder(this)
-                .setCancelable(false)
-                .setView(R.layout.dialog_loading)
-                .create();
-        new AsyncTask<Void, Void, String>() {
-            @Override
-            protected void onPreExecute() {
-                super.onPreExecute();
-                slideShowProgress.show();
-            }
-
-            @Override
-            protected String doInBackground(Void... voids) {
-                Log.v(TAG, "saving svg for slideshow by " + Thread.currentThread().getName());
-                String slideShowFileUri = new File(getCacheDir(), "slideShow.svg").toURI().toString();
-                saveAs(slideShowFileUri, "svg");
-                return slideShowFileUri;
-            }
-
-            @Override
-            protected void onPostExecute(String slideShowFileUri) {
-                super.onPostExecute(slideShowFileUri);
-                slideShowProgress.dismiss();
-                Intent slideShowActIntent = new Intent(MainActivity.this, SlideShowActivity.class);
-                slideShowActIntent.putExtra(SlideShowActivity.SVG_URI_KEY, slideShowFileUri);
-                startActivity(slideShowActIntent);
-            }
-        }.execute();
-    }
-
-    public native void saveAs(String fileUri, String format);
+import org.libreoffice.androidlib.LOActivity;
 
+public class MainActivity extends LOActivity {
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/android/app/src/main/java/org/libreoffice/androidapp/ui/LibreOfficeUIActivity.java b/android/app/src/main/java/org/libreoffice/androidapp/ui/LibreOfficeUIActivity.java
index cc0bb1bc9..9e3f87e22 100644
--- a/android/app/src/main/java/org/libreoffice/androidapp/ui/LibreOfficeUIActivity.java
+++ b/android/app/src/main/java/org/libreoffice/androidapp/ui/LibreOfficeUIActivity.java
@@ -32,7 +32,6 @@ import android.os.Handler;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.text.Editable;
-import android.text.InputType;
 import android.text.TextWatcher;
 import android.util.Log;
 import android.view.ContextMenu;
@@ -70,11 +69,8 @@ import org.libreoffice.androidapp.storage.DocumentProviderSettingsActivity;
 import org.libreoffice.androidapp.storage.IDocumentProvider;
 import org.libreoffice.androidapp.storage.IFile;
 
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileFilter;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FilenameFilter;
 import java.io.IOException;
diff --git a/android/lib/.gitignore b/android/lib/.gitignore
new file mode 100644
index 000000000..77eda0d14
--- /dev/null
+++ b/android/lib/.gitignore
@@ -0,0 +1,3 @@
+/build
+/lib.iml
+/libSettings.gradle
diff --git a/android/lib/build.gradle b/android/lib/build.gradle
new file mode 100644
index 000000000..f208d302b
--- /dev/null
+++ b/android/lib/build.gradle
@@ -0,0 +1,210 @@
+apply plugin: 'com.android.library'
+
+// buildhost settings - paths and the like
+apply from: 'libSettings.gradle'
+
+android {
+    compileSdkVersion 28
+
+    defaultConfig {
+        minSdkVersion 21
+        targetSdkVersion 28
+        versionCode 1
+        versionName "1.0"
+    }
+
+    buildTypes {
+        debug {
+            ndk {
+                //abiFilters "x86", "armeabi-v7a", "armeabi"
+                abiFilters "armeabi-v7a"
+            }
+            debuggable true
+        }
+        release {
+            ndk {
+                abiFilters "armeabi-v7a"
+            }
+            minifyEnabled false // FIXME disabled before we get a good proguardRules for callFakeWebsocketOnMessage calling from C++
+            shrinkResources false // FIXME cannot be enabled when minifyEnabled is turned off
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+    sourceSets {
+        main {
+            // let gradle pack the shared library into apk
+            jniLibs.srcDirs = ['src/main/cpp/lib']
+        }
+    }
+
+    externalNativeBuild {
+        cmake {
+            path "src/main/cpp/CMakeLists.txt"
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'androidx.appcompat:appcompat:1.0.2'
+    implementation 'com.google.android.material:material:1.1.0-alpha04'
+}
+
+task copyUnpackAssets(type: Copy) {
+    description "copies assets that need to be extracted on the device"
+    into 'src/main/assets/unpack'
+    into('program') {
+        from("${liboInstdir}/${liboEtcFolder}/types") {
+            includes = [
+                    "offapi.rdb",
+                    "oovbaapi.rdb"
+            ]
+        }
+        from("${liboInstdir}/${liboUreMiscFolder}") {
+            includes = ["types.rdb"]
+            rename 'types.rdb', 'udkapi.rdb'
+        }
+    }
+    into('user/fonts') {
+        from "${liboInstdir}/share/fonts/truetype"
+        // Note: restrict list of fonts due to size considerations - no technical reason anymore
+        // ToDo: fonts would be good candidate for using Expansion Files instead
+        includes = [
+                "Liberation*.ttf",
+                "Caladea-*.ttf",
+                "Carlito-*.ttf",
+                "Gen*.ttf",
+                "opens___.ttf"
+        ]
+    }
+    into('etc/fonts') {
+        from "${liboSrcRoot}/android/source/"
+        includes = ['fonts.conf']
+        filter {
+            String line ->
+                line.replaceAll(
+                    '@@APPLICATION_ID@@', new String("${android.defaultConfig.applicationId}")
+                ).replaceAll(
+                    // FIXME Avoid the Android system fonts for the moment,
+                    // the huge Noto Sans fonts have terrible impact on the 1st
+                    // start performance.
+                    // The real solution would be to either make fontconfig
+                    // faster, or at least find a way to avoid only the Noto
+                    // Sans, or present a progressbar or something.
+                    // For the moment, we just copy the Roboto font (needed
+                    // for the dialogs; see LOActivity.copyFonts()) and
+                    // remove the system fonts from the config.
+                    '<dir>/system/fonts</dir>', new String("")
+                )
+        }
+    }
+}
+
+task copyAssets(type: Copy) {
+    description "copies assets that can be accessed within the installed apk"
+    into 'src/main/assets'
+    from("${liboSrcRoot}/instdir/") {
+        includes = ["LICENSE.html", "NOTICE"]
+        rename "LICENSE.html", "license.html"
+        rename "NOTICE", "notice.txt"
+    }
+    from("${liboExampleDocument}") {
+        rename ".*", "example.odt"
+    }
+    into('program') {
+        from "${liboInstdir}/program"
+        includes = ['services.rdb', 'services/services.rdb']
+
+        into('resource') {
+            from "${liboInstdir}/${liboSharedResFolder}"
+            includes = ['*en-US.res']
+        }
+    }
+    into('share') {
+        from "${liboInstdir}/share"
+        // Filter data is needed by e.g. the drawingML preset shape import.
+        includes = ['registry/**', 'filter/**']
+    }
+}
+
+task createFullConfig(type: Copy) {
+    description "copies various configuration bits into the apk"
+    into('src/main/assets/share/config')
+    from("${liboInstdir}/share/config") {
+        includes = ['soffice.cfg/**', 'images_colibre.zip']
+    }
+}
+
+task createStrippedConfig {
+    def preserveDir = file("src/main/assets/share/config/soffice.cfg/empty")
+    outputs.dir "src/main/assets/share/registry/res"
+    outputs.file preserveDir
+
+    doLast {
+        file('src/main/assets/share/registry/res').mkdirs()
+        file("src/main/assets/share/config/soffice.cfg").mkdirs()
+        // just empty file
+        preserveDir.text = ""
+    }
+}
+
+task createRCfiles {
+    inputs.file "libSettings.gradle"
+    dependsOn copyUnpackAssets, copyAssets
+    def sofficerc = file('src/main/assets/unpack/program/sofficerc')
+    def fundamentalrc = file('src/main/assets/program/fundamentalrc')
+    def bootstraprc = file('src/main/assets/program/bootstraprc')
+    def unorc = file('src/main/assets/program/unorc')
+    def versionrc = file('src/main/assets/program/versionrc')
+
+    outputs.files sofficerc, fundamentalrc, unorc, bootstraprc, versionrc
+
+    doLast {
+        sofficerc.text = '''\
+[Bootstrap]
+Logo=1
+NativeProgress=1
+URE_BOOTSTRAP=file:///assets/program/fundamentalrc
+HOME=$APP_DATA_DIR/cache
+OSL_SOCKET_PATH=$APP_DATA_DIR/cache
+'''.stripIndent()
+
+        fundamentalrc.text = '''\
+[Bootstrap]
+LO_LIB_DIR=file://$APP_DATA_DIR/lib/
+BRAND_BASE_DIR=file:///assets
+BRAND_SHARE_SUBDIR=share
+CONFIGURATION_LAYERS=xcsxcu:${BRAND_BASE_DIR}/share/registry res:${BRAND_BASE_DIR}/share/registry
+URE_BIN_DIR=file:///assets/ure/bin/dir/nothing-here/we-can/exec-anyway
+'''.stripIndent()
+
+        bootstraprc.text = '''\
+[Bootstrap]
+InstallMode=<installmode>
+ProductKey=LibreOffice ''' + "${liboVersionMajor}.${liboVersionMinor}" + '''
+UserInstallation=file://$APP_DATA_DIR
+'''.stripIndent()
+
+        unorc.text = '''\
+[Bootstrap]
+URE_INTERNAL_LIB_DIR=file://$APP_DATA_DIR/lib/
+UNO_TYPES=file://$APP_DATA_DIR/program/udkapi.rdb file://$APP_DATA_DIR/program/offapi.rdb file://$APP_DATA_DIR/program/oovbaapi.rdb
+UNO_SERVICES=file:///assets/program/services.rdb file:///assets/program/services/services.rdb
+'''.stripIndent()
+
+        versionrc.text = '''\
+[Version]
+AllLanguages=en-US
+BuildVersion=
+buildid=''' + "${liboGitFullCommit}" + '''
+ReferenceOOoMajorMinor=4.1
+'''.stripIndent()
+    }
+}
+
+// creating the UI stuff is cheap, don't bother only applying it for the flavor..
+preBuild.dependsOn 'createRCfiles',
+        'createFullConfig'
diff --git a/android/app/liboSettings.gradle.in b/android/lib/libSettings.gradle.in
similarity index 54%
rename from android/app/liboSettings.gradle.in
rename to android/lib/libSettings.gradle.in
index 80234582b..3736a35fe 100644
--- a/android/app/liboSettings.gradle.in
+++ b/android/lib/libSettings.gradle.in
@@ -1,22 +1,11 @@
 ext {
     liboSrcRoot         = '@LOBUILDDIR@'
-    liboWorkdir         = '@LOBUILDDIR@/workdir'
     liboInstdir         = '@LOBUILDDIR@/instdir'
     liboEtcFolder       = 'program'
     liboUreMiscFolder   = 'program'
     liboSharedResFolder = 'program/resource'
-    liboUREJavaFolder   = 'program/classes'
-    liboShareJavaFolder = 'program/classes'
     liboExampleDocument = '@LOBUILDDIR@/android/default-document/example.odt'
     liboVersionMajor    = '@LOOLWSD_VERSION_MAJOR@'
     liboVersionMinor    = '@LOOLWSD_VERSION_MAJOR@'
     liboGitFullCommit   = '@LOOLWSD_VERSION_HASH@'
-    liboAppName         = '@APP_NAME@'
-    liboVendor          = '@VENDOR@'
-    liboInfoURL         = '@INFO_URL@'
-}
-android.defaultConfig {
-    applicationId '@ANDROID_PACKAGE_NAME@'
-    versionCode 1
-    versionName '@LOOLWSD_VERSION@'
 }
diff --git a/android/lib/proguard-rules.pro b/android/lib/proguard-rules.pro
new file mode 100644
index 000000000..f1b424510
--- /dev/null
+++ b/android/lib/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/android/lib/src/main/AndroidManifest.xml b/android/lib/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..4738b240d
--- /dev/null
+++ b/android/lib/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.libreoffice.androidlib" />
diff --git a/android/app/src/main/cpp/CMakeLists.txt.in b/android/lib/src/main/cpp/CMakeLists.txt.in
similarity index 100%
rename from android/app/src/main/cpp/CMakeLists.txt.in
rename to android/lib/src/main/cpp/CMakeLists.txt.in
diff --git a/android/app/src/main/cpp/androidapp.cpp b/android/lib/src/main/cpp/androidapp.cpp
similarity index 92%
rename from android/app/src/main/cpp/androidapp.cpp
rename to android/lib/src/main/cpp/androidapp.cpp
index 7f5cf0f74..54541e7c4 100644
--- a/android/app/src/main/cpp/androidapp.cpp
+++ b/android/lib/src/main/cpp/androidapp.cpp
@@ -55,7 +55,7 @@ JNI_OnLoad(JavaVM* vm, void*) {
     return JNI_VERSION_1_6;
 }
 
-static void send2JS(jclass mainActivityClz, jobject mainActivityObj, const std::vector<char>& buffer)
+static void send2JS(jclass loActivityClz, jobject loActivityObj, const std::vector<char>& buffer)
 {
     LOG_DBG("Send to JS: " << LOOLProtocol::getAbbreviatedMessage(buffer.data(), buffer.size()));
 
@@ -133,8 +133,8 @@ static void send2JS(jclass mainActivityClz, jobject mainActivityObj, const std::
     }
 
     jstring jstr = env->NewStringUTF(js.c_str());
-    jmethodID callFakeWebsocket = env->GetMethodID(mainActivityClz, "callFakeWebsocketOnMessage", "(Ljava/lang/String;)V");
-    env->CallVoidMethod(mainActivityObj, callFakeWebsocket, jstr);
+    jmethodID callFakeWebsocket = env->GetMethodID(loActivityClz, "callFakeWebsocketOnMessage", "(Ljava/lang/String;)V");
+    env->CallVoidMethod(loActivityObj, callFakeWebsocket, jstr);
 
     if (env->ExceptionCheck())
         env->ExceptionDescribe();
@@ -144,7 +144,7 @@ static void send2JS(jclass mainActivityClz, jobject mainActivityObj, const std::
 
 /// Handle a message from JavaScript.
 extern "C" JNIEXPORT void JNICALL
-Java_org_libreoffice_androidapp_MainActivity_postMobileMessageNative(JNIEnv *env, jobject instance, jstring message)
+Java_org_libreoffice_androidlib_LOActivity_postMobileMessageNative(JNIEnv *env, jobject instance, jstring message)
 {
     const char *string_value = env->GetStringUTFChars(message, nullptr);
 
@@ -172,10 +172,10 @@ Java_org_libreoffice_androidapp_MainActivity_postMobileMessageNative(JNIEnv *env
 
             // Start another thread to read responses and forward them to the JavaScript
             jclass clz = env->GetObjectClass(instance);
-            jclass mainActivityClz = (jclass) env->NewGlobalRef(clz);
-            jobject mainActivityObj = env->NewGlobalRef(instance);
+            jclass loActivityClz = (jclass) env->NewGlobalRef(clz);
+            jobject loActivityObj = env->NewGlobalRef(instance);
 
-            std::thread([mainActivityClz, mainActivityObj, currentFakeClientFd]
+            std::thread([loActivityClz, loActivityObj, currentFakeClientFd]
                         {
                             Util::setThreadName("app2js");
                             while (true)
@@ -215,7 +215,7 @@ Java_org_libreoffice_androidapp_MainActivity_postMobileMessageNative(JNIEnv *env
                                            return;
                                        std::vector<char> buf(n);
                                        n = fakeSocketRead(currentFakeClientFd, buf.data(), n);
-                                       send2JS(mainActivityClz, mainActivityObj, buf);
+                                       send2JS(loActivityClz, loActivityObj, buf);
                                    }
                                }
                                else
@@ -268,7 +268,7 @@ extern "C" jboolean libreofficekit_initialize(JNIEnv* env, jstring dataDir, jstr
 
 /// Create the LOOLWSD instance.
 extern "C" JNIEXPORT void JNICALL
-Java_org_libreoffice_androidapp_MainActivity_createLOOLWSD(JNIEnv *env, jobject, jstring dataDir, jstring cacheDir, jstring apkFile, jobject assetManager, jstring loadFileURL)
+Java_org_libreoffice_androidlib_LOActivity_createLOOLWSD(JNIEnv *env, jobject, jstring dataDir, jstring cacheDir, jstring apkFile, jobject assetManager, jstring loadFileURL)
 {
     fileURL = std::string(env->GetStringUTFChars(loadFileURL, nullptr));
 
@@ -309,7 +309,7 @@ Java_org_libreoffice_androidapp_MainActivity_createLOOLWSD(JNIEnv *env, jobject,
 
 extern "C"
 JNIEXPORT void JNICALL
-Java_org_libreoffice_androidapp_MainActivity_saveAs(JNIEnv *env, jobject instance,
+Java_org_libreoffice_androidlib_LOActivity_saveAs(JNIEnv *env, jobject instance,
                                                     jstring fileUri_, jstring format_) {
     const char *fileUri = env->GetStringUTFChars(fileUri_, 0);
     const char *format = env->GetStringUTFChars(format_, 0);
diff --git a/android/app/src/main/cpp/androidapp.hpp b/android/lib/src/main/cpp/androidapp.hpp
similarity index 100%
rename from android/app/src/main/cpp/androidapp.hpp
rename to android/lib/src/main/cpp/androidapp.hpp
diff --git a/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java b/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java
new file mode 100644
index 000000000..861c114c4
--- /dev/null
+++ b/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java
@@ -0,0 +1,515 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+package org.libreoffice.androidlib;
+
+import android.Manifest;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.print.PrintAttributes;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintManager;
+import android.util.Log;
+import android.webkit.JavascriptInterface;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.Toast;
+
+import java.io.File;
+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.net.URI;
+import java.net.URISyntaxException;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+public class LOActivity extends AppCompatActivity {
+    final static String TAG = "LOActivity";
+
+    private static final String ASSETS_EXTRACTED_PREFS_KEY = "ASSETS_EXTRACTED";
+    private static final int PERMISSION_READ_EXTERNAL_STORAGE = 777;
+    private static final String KEY_ENABLE_SHOW_DEBUG_INFO = "ENABLE_SHOW_DEBUG_INFO";
+
+    private static final String KEY_PROVIDER_ID = "providerID";
+    private static final String KEY_DOCUMENT_URI = "documentUri";
+    private static final String KEY_IS_EDITABLE = "isEditable";
+    private static final String KEY_INTENT_URI = "intentUri";
+
+    private File mTempFile = null;
+
+    private int providerId;
+
+    @Nullable
+    private URI documentUri;
+
+    private String urlToLoad;
+    private WebView mWebView;
+    private SharedPreferences sPrefs;
+    private Handler mainHandler;
+
+    private boolean isDocEditable = false;
+    private boolean isDocDebuggable = BuildConfig.DEBUG;
+
+    private static boolean copyFromAssets(AssetManager assetManager,
+                                          String fromAssetPath, String targetDir) {
+        try {
+            String[] files = assetManager.list(fromAssetPath);
+
+            boolean res = true;
+            for (String file : files) {
+                String[] dirOrFile = assetManager.list(fromAssetPath + "/" + file);
+                if (dirOrFile.length == 0) {
+                    // noinspection ResultOfMethodCallIgnored
+                    new File(targetDir).mkdirs();
+                    res &= copyAsset(assetManager,
+                            fromAssetPath + "/" + file,
+                            targetDir + "/" + file);
+                } else
+                    res &= copyFromAssets(assetManager,
+                            fromAssetPath + "/" + file,
+                            targetDir + "/" + file);
+            }
+            return res;
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.e(TAG, "copyFromAssets failed: " + e.getMessage());
+            return false;
+        }
+    }
+
+    private static boolean copyAsset(AssetManager assetManager, String fromAssetPath, String toPath) {
+        ReadableByteChannel source = null;
+        FileChannel dest = null;
+        try {
+            try {
+                source = Channels.newChannel(assetManager.open(fromAssetPath));
+                dest = new FileOutputStream(toPath).getChannel();
+                long bytesTransferred = 0;
+                // might not copy all at once, so make sure everything gets copied....
+                ByteBuffer buffer = ByteBuffer.allocate(4096);
+                while (source.read(buffer) > 0) {
+                    buffer.flip();
+                    bytesTransferred += dest.write(buffer);
+                    buffer.clear();
+                }
+                Log.v(TAG, "Success copying " + fromAssetPath + " to " + toPath + " bytes: " + bytesTransferred);
+                return true;
+            } finally {
+                if (dest != null) dest.close();
+                if (source != null) source.close();
+            }
+        } catch (FileNotFoundException e) {
+            Log.e(TAG, "file " + fromAssetPath + " not found! " + e.getMessage());
+            return false;
+        } catch (IOException e) {
+            Log.e(TAG, "failed to copy file " + fromAssetPath + " from assets to " + toPath + " - " + e.getMessage());
+            return false;
+        }
+    }
+
+    /** Copies fonts except the NotoSans from the system to our location.
+     *  This is necessary because the NotoSans is huge and fontconfig needs
+     *  ages to parse them.
+     */
+    private static boolean copyFonts(String fromPath, String targetDir) {
+        try {
+            File target = new File(targetDir);
+            if (!target.exists())
+                target.mkdirs();
+
+            File from = new File(fromPath);
+            File[] files = from.listFiles();
+            for (File fontFile : files) {
+                String fontFileName = fontFile.getName();
+                if (!fontFileName.equals("Roboto-Regular.ttf")) {
+                    Log.i(TAG, "Ignored font file: " + fontFile);
+                    continue;
+                }
+                else {
+                    Log.i(TAG, "Copying font file: " + fontFile);
+                }
+
+                // copy the font file over
+                InputStream in = new FileInputStream(fontFile);
+                try {
+                    OutputStream out = new FileOutputStream(targetDir + "/" + fontFile.getName());
+                    try {
+                        byte[] buffer = new byte[4096];
+                        int len;
+                        while ((len = in.read(buffer)) > 0) {
+                            out.write(buffer, 0, len);
+                        }
+                    } finally {
+                        out.close();
+                    }
+                } finally {
+                    in.close();
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.e(TAG, "copyFonts failed: " + e.getMessage());
+            return false;
+        }
+
+        return true;
+    }
+
+    private void updatePreferences() {
+        if (sPrefs.getInt(ASSETS_EXTRACTED_PREFS_KEY, 0) != BuildConfig.VERSION_CODE) {
+            if (copyFromAssets(getAssets(), "unpack", getApplicationInfo().dataDir) &&
+                    copyFonts("/system/fonts", getApplicationInfo().dataDir + "/user/fonts")) {
+                sPrefs.edit().putInt(ASSETS_EXTRACTED_PREFS_KEY, BuildConfig.VERSION_CODE).apply();
+            }
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        sPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+        updatePreferences();
+
+        setContentView(R.layout.activity_main);
+
+        AssetManager assetManager = getResources().getAssets();
+
+        isDocDebuggable = sPrefs.getBoolean(KEY_ENABLE_SHOW_DEBUG_INFO, false) && BuildConfig.DEBUG;
+
+        ApplicationInfo applicationInfo = getApplicationInfo();
+        String dataDir = applicationInfo.dataDir;
+        Log.i(TAG, String.format("Initializing LibreOfficeKit, dataDir=%s\n", dataDir));
+
+        //redirectStdio(true);
+
+        String cacheDir = getApplication().getCacheDir().getAbsolutePath();
+        String apkFile = getApplication().getPackageResourcePath();
+
+        if (getIntent().getData() != null) {
+
+            if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
+                isDocEditable = false;
+                Toast.makeText(this, getResources().getString(R.string.temp_file_saving_disabled), Toast.LENGTH_SHORT).show();
+                if (copyFileToTemp() && mTempFile != null) {
+                    documentUri = mTempFile.toURI();
+                    urlToLoad = documentUri.toString();
+                    Log.d(TAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath());
+                } else {
+                    // TODO: can't open the file
+                    Log.e(TAG, "couldn't create temporary file from " + getIntent().getData());
+                }
+            } else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) {
+                isDocEditable = true;
+                urlToLoad = getIntent().getData().getPath();
+                Log.d(TAG, "SCHEME_FILE: getPath(): " + getIntent().getData().getPath());
+                // Gather data to rebuild IFile object later
+                providerId = getIntent().getIntExtra(
+                        "org.libreoffice.document_provider_id", 0);
+                documentUri = (URI) getIntent().getSerializableExtra(
+                        "org.libreoffice.document_uri");
+            }
+        } else if (savedInstanceState != null) {
+            getIntent().setAction(Intent.ACTION_VIEW)
+                    .setData(Uri.parse(savedInstanceState.getString(KEY_INTENT_URI)));
+            urlToLoad = getIntent().getData().toString();
+            providerId = savedInstanceState.getInt(KEY_PROVIDER_ID);
+            if (savedInstanceState.getString(KEY_DOCUMENT_URI) != null) {
+                try {
+                    documentUri = new URI(savedInstanceState.getString(KEY_DOCUMENT_URI));
+                    urlToLoad = documentUri.toString();
+                } catch (URISyntaxException e) {
+                    e.printStackTrace();
+                }
+            }
+            isDocEditable = savedInstanceState.getBoolean(KEY_IS_EDITABLE);
+        } else {
+            //User can't reach here but if he/she does then
+            Toast.makeText(this, getString(R.string.failed_to_load_file), Toast.LENGTH_SHORT).show();
+            finish();
+        }
+
+        createLOOLWSD(dataDir, cacheDir, apkFile, assetManager, urlToLoad);
+
+        mWebView = findViewById(R.id.browser);
+        mWebView.setWebViewClient(new WebViewClient());
+
+        WebSettings webSettings = mWebView.getSettings();
+        webSettings.setJavaScriptEnabled(true);
+        mWebView.addJavascriptInterface(this, "LOOLMessageHandler");
+
+        // allow debugging (when building the debug version); see details in
+        // https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+                WebView.setWebContentsDebuggingEnabled(true);
+            }
+        }
+        mainHandler = new Handler(getMainLooper());
+    }
+
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
+            Log.i(TAG, "asking for read storage permission");
+            ActivityCompat.requestPermissions(this,
+                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
+                    PERMISSION_READ_EXTERNAL_STORAGE);
+        } else {
+            loadDocument();
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(@NonNull Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putString(KEY_INTENT_URI, getIntent().getData().toString());
+        outState.putInt(KEY_PROVIDER_ID, providerId);
+        if (documentUri != null) {
+            outState.putString(KEY_DOCUMENT_URI, documentUri.toString());
+        }
+        //If this activity was opened via contentUri
+        outState.putBoolean(KEY_IS_EDITABLE, isDocEditable);
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        switch (requestCode) {
+            case PERMISSION_READ_EXTERNAL_STORAGE:
+                if (permissions.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                    loadDocument();
+                } else {
+                    Toast.makeText(this, getString(R.string.storage_permission_required), Toast.LENGTH_SHORT).show();
+                    finish();
+                    break;
+                }
+                break;
+            default:
+                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        }
+    }
+
+    private boolean copyFileToTemp() {
+        ContentResolver contentResolver = getContentResolver();
+        FileChannel inputChannel = null;
+        FileChannel outputChannel = null;
+        // CSV files need a .csv suffix to be opened in Calc.
+        String suffix = null;
+        String intentType = getIntent().getType();
+        // K-9 mail uses the first, GMail uses the second variant.
+        if ("text/comma-separated-values".equals(intentType) || "text/csv".equals(intentType))
+            suffix = ".csv";
+
+        try {
+            try {
+                AssetFileDescriptor assetFD = contentResolver.openAssetFileDescriptor(getIntent().getData(), "r");
+                if (assetFD == null) {
+                    Log.e(TAG, "couldn't create assetfiledescriptor from " + getIntent().getDataString());
+                    return false;
+                }
+                inputChannel = assetFD.createInputStream().getChannel();
+                mTempFile = File.createTempFile("LibreOffice", suffix, this.getCacheDir());
+
+                outputChannel = new FileOutputStream(mTempFile).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(TAG, "Success copying " + bytesTransferred + " bytes");
+                return true;
+            } finally {
+                if (inputChannel != null) inputChannel.close();
+                if (outputChannel != null) outputChannel.close();
+            }
+        } catch (FileNotFoundException e) {
+            return false;
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        Log.i(TAG, "onResume..");
+
+        // check for config change
+        updatePreferences();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        Log.d(TAG, "onPause() - unload the document");
+        postMobileMessageNative("BYE");
+    }
+
+    private void loadDocument() {
+        String finalUrlToLoad = "file:///android_asset/dist/loleaflet.html?file_path=" +
+                urlToLoad + "&closebutton=1";
+        if (isDocEditable) {
+            finalUrlToLoad += "&permission=edit";
+        } else {
+            finalUrlToLoad += "&permission=readonly";
+        }
+        if (isDocDebuggable) {
+            finalUrlToLoad += "&debug=true";
+        }
+        mWebView.loadUrl(finalUrlToLoad);
+    }
+
+    static {
+        System.loadLibrary("androidapp");
+    }
+
+    /**
+     * Initialize the LOOLWSD to load 'loadFileURL'.
+     */
+    public native void createLOOLWSD(String dataDir, String cacheDir, String apkFile, AssetManager assetManager, String loadFileURL);
+
+    /**
+     * Passing messages from JS (instead of the websocket communication).
+     */
+    @JavascriptInterface
+    public void postMobileMessage(String message) {
+        Log.d(TAG, "postMobileMessage: " + message);
+
+        if (interceptMsgFromWebView(message)) {
+            postMobileMessageNative(message);
+        }
+
+        // Going back to document browser on BYE (called when pressing the top left exit button)
+        if (message.equals("BYE"))
+            finish();
+    }
+
+    /**
+     * Call the post method form C++
+     */
+    public native void postMobileMessageNative(String message);
+
+    /**
+     * Passing messages from JS (instead of the websocket communication).
+     */
+    @JavascriptInterface
+    public void postMobileError(String message) {
+        // TODO handle this
+        Log.d(TAG, "postMobileError: " + message);
+    }
+
+    /**
+     * Passing messages from JS (instead of the websocket communication).
+     */
+    @JavascriptInterface
+    public void postMobileDebug(String message) {
+        // TODO handle this
+        Log.d(TAG, "postMobileDebug: " + message);
+    }
+
+    /**
+     * Passing message the other way around - from Java to the FakeWebSocket in JS.
+     */
+    void callFakeWebsocketOnMessage(final String message) {
+        // call from the UI thread
+        mWebView.post(new Runnable() {
+            public void run() {
+                Log.i(TAG, "Forwarding to the WebView: " + message);
+                mWebView.loadUrl("javascript:window.TheFakeWebSocket.onmessage({'data':" + message + "});");
+            }
+        });
+    }
+
+    /**
+     * return true to pass the message to the native part and false to block the message
+     */
+    boolean interceptMsgFromWebView(String message) {
+        if (message.equals("PRINT")) {
+            mainHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    initiatePrint();
+                }
+            });
+            return false;
+        } else if (message.equals("SLIDESHOW")) {
+            initiateSlideShow();
+            return false;
+        }
+        return true;
+    }
+
+    private void initiatePrint() {
+        PrintManager printManager = (PrintManager) getSystemService(PRINT_SERVICE);
+        PrintDocumentAdapter printAdapter = new PrintAdapter(LOActivity.this);
+        printManager.print("Document", printAdapter, new PrintAttributes.Builder().build());
+    }
+
+    private void initiateSlideShow() {
+        final AlertDialog slideShowProgress = new AlertDialog.Builder(this)
+                .setCancelable(false)
+                .setView(R.layout.dialog_loading)
+                .create();
+        new AsyncTask<Void, Void, String>() {
+            @Override
+            protected void onPreExecute() {
+                super.onPreExecute();
+                slideShowProgress.show();
+            }
+
+            @Override
+            protected String doInBackground(Void... voids) {
+                Log.v(TAG, "saving svg for slideshow by " + Thread.currentThread().getName());
+                String slideShowFileUri = new File(getCacheDir(), "slideShow.svg").toURI().toString();
+                saveAs(slideShowFileUri, "svg");
+                return slideShowFileUri;
+            }
+
+            @Override
+            protected void onPostExecute(String slideShowFileUri) {
+                super.onPostExecute(slideShowFileUri);
+                slideShowProgress.dismiss();
+                Intent slideShowActIntent = new Intent(LOActivity.this, SlideShowActivity.class);
+                slideShowActIntent.putExtra(SlideShowActivity.SVG_URI_KEY, slideShowFileUri);
+                startActivity(slideShowActIntent);
+            }
+        }.execute();
+    }
+
+    public native void saveAs(String fileUri, String format);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/android/app/src/main/java/org/libreoffice/androidapp/PrintAdapter.java b/android/lib/src/main/java/org/libreoffice/androidlib/PrintAdapter.java
similarity index 96%
rename from android/app/src/main/java/org/libreoffice/androidapp/PrintAdapter.java
rename to android/lib/src/main/java/org/libreoffice/androidlib/PrintAdapter.java
index 52f5bcc95..a10349327 100644
--- a/android/app/src/main/java/org/libreoffice/androidapp/PrintAdapter.java
+++ b/android/lib/src/main/java/org/libreoffice/androidlib/PrintAdapter.java
@@ -7,7 +7,7 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-package org.libreoffice.androidapp;
+package org.libreoffice.androidlib;
 
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -28,9 +28,9 @@ import java.util.Objects;
 public class PrintAdapter extends PrintDocumentAdapter {
 
     private File printDocFile;
-    private MainActivity mainActivity;
+    private LOActivity mainActivity;
 
-    PrintAdapter(MainActivity mainActivity) {
+    PrintAdapter(LOActivity mainActivity) {
         this.mainActivity = mainActivity;
     }
 
diff --git a/android/app/src/main/java/org/libreoffice/androidapp/SlideShowActivity.java b/android/lib/src/main/java/org/libreoffice/androidlib/SlideShowActivity.java
similarity index 98%
rename from android/app/src/main/java/org/libreoffice/androidapp/SlideShowActivity.java
rename to android/lib/src/main/java/org/libreoffice/androidlib/SlideShowActivity.java
index 97407eb44..3a957b154 100644
--- a/android/app/src/main/java/org/libreoffice/androidapp/SlideShowActivity.java
+++ b/android/lib/src/main/java/org/libreoffice/androidlib/SlideShowActivity.java
@@ -7,7 +7,7 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-package org.libreoffice.androidapp;
+package org.libreoffice.androidlib;
 
 import androidx.annotation.NonNull;
 import androidx.appcompat.app.AppCompatActivity;
diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/lib/src/main/res/layout/activity_main.xml
similarity index 94%
rename from android/app/src/main/res/layout/activity_main.xml
rename to android/lib/src/main/res/layout/activity_main.xml
index 244e1bb99..2810a9af9 100644
--- a/android/app/src/main/res/layout/activity_main.xml
+++ b/android/lib/src/main/res/layout/activity_main.xml
@@ -4,7 +4,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context=".MainActivity">
+    tools:context=".LOActivity">
 
     <WebView
         android:id="@+id/browser"
diff --git a/android/app/src/main/res/layout/activity_slide_show.xml b/android/lib/src/main/res/layout/activity_slide_show.xml
similarity index 100%
rename from android/app/src/main/res/layout/activity_slide_show.xml
rename to android/lib/src/main/res/layout/activity_slide_show.xml
diff --git a/android/app/src/main/res/layout/dialog_loading.xml b/android/lib/src/main/res/layout/dialog_loading.xml
similarity index 100%
rename from android/app/src/main/res/layout/dialog_loading.xml
rename to android/lib/src/main/res/layout/dialog_loading.xml
diff --git a/android/lib/src/main/res/values/strings.xml b/android/lib/src/main/res/values/strings.xml
new file mode 100644
index 000000000..5651df183
--- /dev/null
+++ b/android/lib/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+<resources>
+    <string name="temp_file_saving_disabled">This file is read-only, saving is disabled.</string>
+    <string name="storage_permission_required">Storage permission is required</string>
+    <string name="failed_to_load_file">Failed to determine the file to load</string>
+
+    <!-- Loading SlideShow Dialog Strings -->
+    <string name="loading">Loading...</string>
+</resources>
\ No newline at end of file
diff --git a/android/settings.gradle b/android/settings.gradle
index e7b4def49..3cbe24935 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1 +1 @@
-include ':app'
+include ':app', ':lib'
diff --git a/configure.ac b/configure.ac
index c9446f35a..681d5bdde 100644
--- a/configure.ac
+++ b/configure.ac
@@ -790,8 +790,9 @@ AS_IF([test "$ENABLE_IOSAPP" = "true"],
 AC_SUBST(IOSAPP_FONTS)
 
 AC_CONFIG_FILES([Makefile
-                 android/app/liboSettings.gradle
-                 android/app/src/main/cpp/CMakeLists.txt
+                 android/app/appSettings.gradle
+                 android/lib/libSettings.gradle
+                 android/lib/src/main/cpp/CMakeLists.txt
                  android/Makefile
                  gtk/Makefile
                  ios/config.h
diff --git a/loleaflet/Makefile.am b/loleaflet/Makefile.am
index 2106a0846..5ec53ce0f 100644
--- a/loleaflet/Makefile.am
+++ b/loleaflet/Makefile.am
@@ -152,13 +152,13 @@ build-loleaflet: | $(LOLEAFLET_L10N_DST) \
 	$(builddir)/dist/loleaflet.html
 	@echo "build loleaflet completed"
 if ENABLE_ANDROIDAPP
-	@rm -rf $(abs_top_srcdir)/android/app/src/main/assets/dist
-	@cp -a $(builddir)/dist $(abs_top_srcdir)/android/app/src/main/assets/
-	@if test -d "$(APP_BRANDING_DIR)" ; then cp -a "$(APP_BRANDING_DIR)/branding.css" "$(APP_BRANDING_DIR)/branding.js" $(abs_top_srcdir)/android/app/src/main/assets/dist/ ; else touch $(abs_top_srcdir)/android/app/src/main/assets/dist/branding.css ; fi
-	@if test -d "$(APP_BRANDING_DIR)" ; then cp -a "$(APP_BRANDING_DIR)"/*.svg $(abs_top_srcdir)/android/app/src/main/assets/dist/images/ ; fi
-	@if test -d "$(APP_BRANDING_DIR)" ; then cp -a "$(APP_BRANDING_DIR)/toolbar-bg-logo.svg" $(abs_top_srcdir)/android/app/src/main/assets/dist/images/toolbar-bg.svg ; fi
+	@rm -rf $(abs_top_srcdir)/android/lib/src/main/assets/dist
+	@cp -a $(builddir)/dist $(abs_top_srcdir)/android/lib/src/main/assets/
+	@if test -d "$(APP_BRANDING_DIR)" ; then cp -a "$(APP_BRANDING_DIR)/branding.css" "$(APP_BRANDING_DIR)/branding.js" $(abs_top_srcdir)/android/lib/src/main/assets/dist/ ; else touch $(abs_top_srcdir)/android/lib/src/main/assets/dist/branding.css ; fi
+	@if test -d "$(APP_BRANDING_DIR)" ; then cp -a "$(APP_BRANDING_DIR)"/*.svg $(abs_top_srcdir)/android/lib/src/main/assets/dist/images/ ; fi
+	@if test -d "$(APP_BRANDING_DIR)" ; then cp -a "$(APP_BRANDING_DIR)/toolbar-bg-logo.svg" $(abs_top_srcdir)/android/lib/src/main/assets/dist/images/toolbar-bg.svg ; fi
 	@echo
-	@echo "Copied JS, HTML and CSS to the Android project (android/app/src/main/assets/dist)."
+	@echo "Copied JS, HTML and CSS to the Android project (android/lib/src/main/assets/dist)."
 	@echo
 	@echo "  Now you need to build the actual .apk from Android Studio:"
 	@echo "  Just open the 'android' subdir as a project there and build."


More information about the Libreoffice-commits mailing list