summaryrefslogtreecommitdiffstats
path: root/android/source/src/java/org/libreoffice/ui
diff options
context:
space:
mode:
Diffstat (limited to 'android/source/src/java/org/libreoffice/ui')
-rw-r--r--android/source/src/java/org/libreoffice/ui/FileUtilities.java153
-rw-r--r--android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java473
-rw-r--r--android/source/src/java/org/libreoffice/ui/PageView.java69
-rw-r--r--android/source/src/java/org/libreoffice/ui/RecentFile.java25
-rw-r--r--android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java93
5 files changed, 813 insertions, 0 deletions
diff --git a/android/source/src/java/org/libreoffice/ui/FileUtilities.java b/android/source/src/java/org/libreoffice/ui/FileUtilities.java
new file mode 100644
index 000000000..902b30ed7
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/ui/FileUtilities.java
@@ -0,0 +1,153 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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.ui;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.OpenableColumns;
+import android.util.Log;
+
+public class FileUtilities {
+
+ private static final String LOGTAG = FileUtilities.class.getSimpleName();
+
+ // These have to be in sync with the file_view_modes resource.
+ static final int DOC = 0;
+ static final int CALC = 1;
+ static final int IMPRESS = 2;
+ static final int DRAWING = 3;
+
+ static final int UNKNOWN = 10;
+
+ public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text";
+ public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet";
+ public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION = "application/vnd.oasis.opendocument.presentation";
+ public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS = "application/vnd.oasis.opendocument.graphics";
+ public static final String MIMETYPE_PDF = "application/pdf";
+
+ private static final Map<String, Integer> mExtnMap = new HashMap<String, Integer>();
+ static {
+ // Please keep this in sync with AndroidManifest.xml
+ // and 'SUPPORTED_MIME_TYPES' in LibreOfficeUIActivity.java
+
+ // ODF
+ mExtnMap.put(".odt", DOC);
+ mExtnMap.put(".odg", DRAWING);
+ mExtnMap.put(".odp", IMPRESS);
+ mExtnMap.put(".ods", CALC);
+ mExtnMap.put(".fodt", DOC);
+ mExtnMap.put(".fodg", DRAWING);
+ mExtnMap.put(".fodp", IMPRESS);
+ mExtnMap.put(".fods", CALC);
+
+ // ODF templates
+ mExtnMap.put(".ott", DOC);
+ mExtnMap.put(".otg", DRAWING);
+ mExtnMap.put(".otp", IMPRESS);
+ mExtnMap.put(".ots", CALC);
+
+ // MS
+ mExtnMap.put(".rtf", DOC);
+ mExtnMap.put(".doc", DOC);
+ mExtnMap.put(".vsd", DRAWING);
+ mExtnMap.put(".vsdx", DRAWING);
+ mExtnMap.put(".pub", DRAWING);
+ mExtnMap.put(".ppt", IMPRESS);
+ mExtnMap.put(".pps", IMPRESS);
+ mExtnMap.put(".xls", CALC);
+
+ // MS templates
+ mExtnMap.put(".dot", DOC);
+ mExtnMap.put(".pot", IMPRESS);
+ mExtnMap.put(".xlt", CALC);
+
+ // OOXML
+ mExtnMap.put(".docx", DOC);
+ mExtnMap.put(".pptx", IMPRESS);
+ mExtnMap.put(".ppsx", IMPRESS);
+ mExtnMap.put(".xlsx", CALC);
+
+ // OOXML templates
+ mExtnMap.put(".dotx", DOC);
+ mExtnMap.put(".potx", IMPRESS);
+ mExtnMap.put(".xltx", CALC);
+
+ // Other
+ mExtnMap.put(".csv", CALC);
+ mExtnMap.put(".wps", DOC);
+ mExtnMap.put(".key", IMPRESS);
+ mExtnMap.put(".abw", DOC);
+ mExtnMap.put(".pmd", DRAWING);
+ mExtnMap.put(".emf", DRAWING);
+ mExtnMap.put(".svm", DRAWING);
+ mExtnMap.put(".wmf", DRAWING);
+ mExtnMap.put(".svg", DRAWING);
+ }
+
+ public static String getExtension(String filename) {
+ if (filename == null)
+ return "";
+ int nExt = filename.lastIndexOf('.');
+ if (nExt < 0)
+ return "";
+ return filename.substring(nExt);
+ }
+
+ private static int lookupExtension(String filename) {
+ String extn = getExtension(filename);
+ if (!mExtnMap.containsKey(extn))
+ return UNKNOWN;
+ return mExtnMap.get(extn);
+ }
+
+ static int getType(String filename) {
+ int type = lookupExtension (filename);
+ Log.d(LOGTAG, "extn : " + filename + " -> " + type);
+ return type;
+ }
+
+ /**
+ * Returns whether the passed MIME type is one for a document template.
+ */
+ public static boolean isTemplateMimeType(final String mimeType) {
+ // this works for ODF and OOXML template MIME types
+ return mimeType != null && mimeType.endsWith("template");
+ }
+
+ /**
+ * Tries to retrieve the display (which should be the document name)
+ * for the given URI using the given resolver.
+ */
+ public static String retrieveDisplayNameForDocumentUri(ContentResolver resolver, Uri docUri) {
+ String displayName = "";
+ // try to retrieve original file name
+ Cursor cursor = null;
+ try {
+ String[] columns = {OpenableColumns.DISPLAY_NAME};
+ cursor = resolver.query(docUri, columns, null, null, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ displayName = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
+ }
+ } catch (SecurityException e) {
+ // thrown e.g. when Uri has become invalid, e.g. corresponding file has been deleted
+ Log.i(LOGTAG, "SecurityException when trying to receive display name for Uri " + docUri);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return displayName;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
new file mode 100644
index 000000000..a5fa78f22
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
@@ -0,0 +1,473 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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.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;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.core.view.ViewCompat;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.appcompat.widget.Toolbar;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.OvershootInterpolator;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import org.libreoffice.AboutDialogFragment;
+import org.libreoffice.LibreOfficeMainActivity;
+import org.libreoffice.LocaleHelper;
+import org.libreoffice.R;
+import org.libreoffice.SettingsActivity;
+import org.libreoffice.SettingsListenerModel;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class LibreOfficeUIActivity extends AppCompatActivity implements SettingsListenerModel.OnSettingsPreferenceChangedListener, View.OnClickListener{
+ public enum DocumentType {
+ WRITER,
+ CALC,
+ IMPRESS,
+ DRAW,
+ INVALID
+ }
+
+ private static final String LOGTAG = LibreOfficeUIActivity.class.getSimpleName();
+
+ public static final String EXPLORER_PREFS_KEY = "EXPLORER_PREFS";
+ private static final String RECENT_DOCUMENTS_KEY = "RECENT_DOCUMENT_URIS";
+ // delimiter used for storing multiple URIs in a string
+ private static final String RECENT_DOCUMENTS_DELIMITER = " ";
+ private static final String DISPLAY_LANGUAGE = "DISPLAY_LANGUAGE";
+
+ public static final String NEW_DOC_TYPE_KEY = "NEW_DOC_TYPE_KEY";
+ public static final String NEW_WRITER_STRING_KEY = "private:factory/swriter";
+ public static final String NEW_IMPRESS_STRING_KEY = "private:factory/simpress";
+ public static final String NEW_CALC_STRING_KEY = "private:factory/scalc";
+ public static final String NEW_DRAW_STRING_KEY = "private:factory/sdraw";
+
+ // keep this in sync with 'AndroidManifext.xml'
+ private static final String[] SUPPORTED_MIME_TYPES = {
+ "application/vnd.oasis.opendocument.text",
+ "application/vnd.oasis.opendocument.graphics",
+ "application/vnd.oasis.opendocument.presentation",
+ "application/vnd.oasis.opendocument.spreadsheet",
+ "application/vnd.oasis.opendocument.text-flat-xml",
+ "application/vnd.oasis.opendocument.graphics-flat-xml",
+ "application/vnd.oasis.opendocument.presentation-flat-xml",
+ "application/vnd.oasis.opendocument.spreadsheet-flat-xml",
+ "application/vnd.oasis.opendocument.text-template",
+ "application/vnd.oasis.opendocument.spreadsheet-template",
+ "application/vnd.oasis.opendocument.graphics-template",
+ "application/vnd.oasis.opendocument.presentation-template",
+ "application/rtf",
+ "text/rtf",
+ "application/msword",
+ "application/vnd.ms-powerpoint",
+ "application/vnd.ms-excel",
+ "application/vnd.visio",
+ "application/vnd.visio.xml",
+ "application/x-mspublisher",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
+ "application/vnd.openxmlformats-officedocument.presentationml.template",
+ "text/csv",
+ "text/comma-separated-values",
+ "application/vnd.ms-works",
+ "application/vnd.apple.keynote",
+ "application/x-abiword",
+ "application/x-pagemaker",
+ "image/x-emf",
+ "image/x-svm",
+ "image/x-wmf",
+ "image/svg+xml",
+ };
+
+ private static final int REQUEST_CODE_OPEN_FILECHOOSER = 12345;
+
+ private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
+
+ private Animation fabOpenAnimation;
+ private Animation fabCloseAnimation;
+ private boolean isFabMenuOpen = false;
+ private FloatingActionButton editFAB;
+ private FloatingActionButton writerFAB;
+ private FloatingActionButton drawFAB;
+ private FloatingActionButton impressFAB;
+ private FloatingActionButton calcFAB;
+ private LinearLayout drawLayout;
+ private LinearLayout writerLayout;
+ private LinearLayout impressLayout;
+ private LinearLayout calcLayout;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ readPreferences();
+ SettingsListenerModel.getInstance().setListener(this);
+
+ // init UI
+ createUI();
+ fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open);
+ 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));
+ }
+
+ public void createUI() {
+ setContentView(R.layout.activity_document_browser);
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ ActionBar actionBar = getSupportActionBar();
+
+ if (actionBar != null) {
+ actionBar.setIcon(R.drawable.lo_icon);
+ }
+
+ editFAB = findViewById(R.id.editFAB);
+ editFAB.setOnClickListener(this);
+ impressFAB = findViewById(R.id.newImpressFAB);
+ impressFAB.setOnClickListener(this);
+ writerFAB = findViewById(R.id.newWriterFAB);
+ writerFAB.setOnClickListener(this);
+ calcFAB = findViewById(R.id.newCalcFAB);
+ calcFAB.setOnClickListener(this);
+ drawFAB = findViewById(R.id.newDrawFAB);
+ drawFAB.setOnClickListener(this);
+ writerLayout = findViewById(R.id.writerLayout);
+ impressLayout = findViewById(R.id.impressLayout);
+ calcLayout = findViewById(R.id.calcLayout);
+ drawLayout = findViewById(R.id.drawLayout);
+ TextView openFileView = findViewById(R.id.open_file_view);
+ openFileView.setOnClickListener(this);
+
+
+ RecyclerView recentRecyclerView = findViewById(R.id.list_recent);
+
+ SharedPreferences prefs = getSharedPreferences(EXPLORER_PREFS_KEY, MODE_PRIVATE);
+ String recentPref = prefs.getString(RECENT_DOCUMENTS_KEY, "");
+ String[] recentFileStrings = recentPref.split(RECENT_DOCUMENTS_DELIMITER);
+
+ final List<RecentFile> recentFiles = new ArrayList<>();
+ for (String recentFileString : recentFileStrings) {
+ Uri uri = Uri.parse(recentFileString);
+ String filename = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), uri);
+ if (!filename.isEmpty()) {
+ recentFiles.add(new RecentFile(uri, filename));
+ }
+ }
+
+ recentRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
+ recentRecyclerView.setAdapter(new RecentFilesAdapter(this, recentFiles));
+ }
+
+ private void expandFabMenu() {
+ ViewCompat.animate(editFAB).rotation(45.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
+ drawLayout.startAnimation(fabOpenAnimation);
+ impressLayout.startAnimation(fabOpenAnimation);
+ writerLayout.startAnimation(fabOpenAnimation);
+ calcLayout.startAnimation(fabOpenAnimation);
+ writerFAB.setClickable(true);
+ impressFAB.setClickable(true);
+ drawFAB.setClickable(true);
+ calcFAB.setClickable(true);
+ isFabMenuOpen = true;
+ }
+
+ private void collapseFabMenu() {
+ ViewCompat.animate(editFAB).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
+ writerLayout.startAnimation(fabCloseAnimation);
+ impressLayout.startAnimation(fabCloseAnimation);
+ drawLayout.startAnimation(fabCloseAnimation);
+ calcLayout.startAnimation(fabCloseAnimation);
+ writerFAB.setClickable(false);
+ impressFAB.setClickable(false);
+ drawFAB.setClickable(false);
+ calcFAB.setClickable(false);
+ isFabMenuOpen = false;
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (isFabMenuOpen) {
+ collapseFabMenu();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_CODE_OPEN_FILECHOOSER && resultCode == RESULT_OK) {
+ final Uri fileUri = data.getData();
+ openDocument(fileUri);
+ }
+ }
+
+ private void showSystemFilePickerAndOpenFile() {
+ Intent intent = new Intent();
+ if (Build.VERSION.SDK_INT >= 19) {
+ intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
+ }
+ else {
+ // Intent.ACTION_OPEN_DOCUMENT added in API level 19, but minSdkVersion is currently 16
+ intent.setAction(Intent.ACTION_GET_CONTENT);
+ }
+
+ intent.setType("*/*");
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, SUPPORTED_MIME_TYPES);
+
+ try {
+ startActivityForResult(intent, REQUEST_CODE_OPEN_FILECHOOSER);
+ } catch (ActivityNotFoundException e) {
+ Log.w(LOGTAG, "No activity available that can handle the intent to open a document.");
+ }
+ }
+
+ public void openDocument(final Uri documentUri) {
+ // "forward" to LibreOfficeMainActivity to open the file
+ Intent intent = new Intent(Intent.ACTION_VIEW, documentUri);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ addDocumentToRecents(documentUri);
+
+ String packageName = getApplicationContext().getPackageName();
+ ComponentName componentName = new ComponentName(packageName,
+ LibreOfficeMainActivity.class.getName());
+ intent.setComponent(componentName);
+ startActivity(intent);
+ }
+
+ private void loadNewDocument(DocumentType docType) {
+ final String newDocumentType;
+ if (docType == DocumentType.WRITER) {
+ newDocumentType = NEW_WRITER_STRING_KEY;
+ } else if (docType == DocumentType.CALC) {
+ newDocumentType = NEW_CALC_STRING_KEY;
+ } else if (docType == DocumentType.IMPRESS) {
+ newDocumentType = NEW_IMPRESS_STRING_KEY;
+ } else if (docType == DocumentType.DRAW) {
+ newDocumentType = NEW_DRAW_STRING_KEY;
+ } else {
+ Log.w(LOGTAG, "invalid document type passed to loadNewDocument method. Ignoring request");
+ return;
+ }
+
+ Intent intent = new Intent(LibreOfficeUIActivity.this, LibreOfficeMainActivity.class);
+ intent.putExtra(NEW_DOC_TYPE_KEY, newDocumentType);
+ startActivity(intent);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.view_menu, menu);
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == R.id.action_about) {
+ AboutDialogFragment aboutDialogFragment = new AboutDialogFragment();
+ aboutDialogFragment.show(getSupportFragmentManager(), "AboutDialogFragment");
+ return true;
+ }
+ if (itemId == R.id.action_settings) {
+ startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ public void readPreferences(){
+ SharedPreferences defaultPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
+ final String displayLanguage = defaultPrefs.getString(DISPLAY_LANGUAGE, LocaleHelper.SYSTEM_DEFAULT_LANGUAGE);
+ LocaleHelper.setLocale(this, displayLanguage);
+ }
+
+ @Override
+ public void settingsPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ readPreferences();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Log.d(LOGTAG, "onResume");
+ createUI();
+ }
+
+ private void addDocumentToRecents(Uri fileUri) {
+ SharedPreferences prefs = getSharedPreferences(EXPLORER_PREFS_KEY, MODE_PRIVATE);
+ if (Build.VERSION.SDK_INT < 19) {
+ // ContentResolver#takePersistableUriPermission only available from SDK level 19 on
+ Log.i(LOGTAG, "Recently used files not supported, requires SDK version >= 19.");
+ // drop potential entries
+ prefs.edit().putString(RECENT_DOCUMENTS_KEY, "").apply();
+ return;
+ }
+
+ // preserve permissions across device reboots,
+ // s. https://developer.android.com/training/data-storage/shared/documents-files#persist-permissions
+ getContentResolver().takePersistableUriPermission(fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ String newRecent = fileUri.toString();
+ List<String> recentsList = new ArrayList<>(Arrays.asList(prefs.getString(RECENT_DOCUMENTS_KEY, "").split(RECENT_DOCUMENTS_DELIMITER)));
+
+ // remove string if present, so that it doesn't appear multiple times
+ recentsList.remove(newRecent);
+
+ // put the new value in the first place
+ recentsList.add(0, newRecent);
+
+ /*
+ * 4 because the number of recommended items in App Shortcuts is 4, and also
+ * because it's a good number of recent items in general
+ */
+ final int RECENTS_SIZE = 4;
+
+ while (recentsList.size() > RECENTS_SIZE) {
+ recentsList.remove(RECENTS_SIZE);
+ }
+
+ // serialize to String that can be set for pref
+ String value = TextUtils.join(RECENT_DOCUMENTS_DELIMITER, recentsList);
+ prefs.edit().putString(RECENT_DOCUMENTS_KEY, value).apply();
+
+ //update app shortcuts (7.0 and above)
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) {
+ ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
+
+ //Remove all shortcuts, and apply new ones.
+ shortcutManager.removeAllDynamicShortcuts();
+
+ ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+ for (String recentDoc : recentsList) {
+ Uri docUri = Uri.parse(recentDoc);
+ String filename = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), docUri);
+ if (filename.isEmpty()) {
+ continue;
+ }
+
+ //find the appropriate drawable
+ int drawable = 0;
+ switch (FileUtilities.getType(filename)) {
+ case FileUtilities.DOC:
+ drawable = R.drawable.writer;
+ break;
+ case FileUtilities.CALC:
+ drawable = R.drawable.calc;
+ break;
+ case FileUtilities.DRAWING:
+ drawable = R.drawable.draw;
+ break;
+ case FileUtilities.IMPRESS:
+ drawable = R.drawable.impress;
+ break;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_VIEW, docUri);
+ String packageName = this.getApplicationContext().getPackageName();
+ ComponentName componentName = new ComponentName(packageName, LibreOfficeMainActivity.class.getName());
+ intent.setComponent(componentName);
+
+ ShortcutInfo shortcut = new ShortcutInfo.Builder(this, filename)
+ .setShortLabel(filename)
+ .setLongLabel(filename)
+ .setIcon(Icon.createWithResource(this, drawable))
+ .setIntent(intent)
+ .build();
+
+ shortcuts.add(shortcut);
+ }
+ shortcutManager.setDynamicShortcuts(shortcuts);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+ if (id == R.id.editFAB) {
+ // Intent.ACTION_CREATE_DOCUMENT, used in 'createNewFileDialog' requires SDK version 19
+ if (Build.VERSION.SDK_INT < 19) {
+ Toast.makeText(this,
+ getString(R.string.creating_new_files_not_supported), Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (isFabMenuOpen) {
+ collapseFabMenu();
+ } else {
+ expandFabMenu();
+ }
+ } else if (id == R.id.open_file_view) {
+ showSystemFilePickerAndOpenFile();
+ } else if (id == R.id.newWriterFAB) {
+ loadNewDocument(DocumentType.WRITER);
+ } else if (id == R.id.newImpressFAB) {
+ loadNewDocument(DocumentType.IMPRESS);
+ } else if (id == R.id.newCalcFAB) {
+ loadNewDocument(DocumentType.CALC);
+ } else if (id == R.id.newDrawFAB) {
+ loadNewDocument(DocumentType.DRAW);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/ui/PageView.java b/android/source/src/java/org/libreoffice/ui/PageView.java
new file mode 100644
index 000000000..4c3f69562
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/ui/PageView.java
@@ -0,0 +1,69 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+package org.libreoffice.ui;
+
+import org.libreoffice.R;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+public class PageView extends View{
+ private Bitmap bmp;
+ private Paint mPaintBlack;
+ private static final String LOGTAG = "PageView";
+
+ public PageView(Context context ) {
+ super(context);
+ bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page);
+ initialise();
+ }
+ public PageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page);
+ Log.d(LOGTAG, bmp.toString());
+ initialise();
+ }
+ public PageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page);//load a "page"
+ initialise();
+ }
+
+ private void initialise(){
+ mPaintBlack = new Paint();
+ mPaintBlack.setARGB(255, 0, 0, 0);
+ Log.d(LOGTAG, " Doing some set-up");
+ }
+
+ public void setBitmap(Bitmap bmp){
+ this.bmp = bmp;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ Log.d(LOGTAG, "Draw");
+ Log.d(LOGTAG, Integer.toString(bmp.getHeight()));
+ if( bmp != null ){
+ int horizontalMargin = (int) (canvas.getWidth()*0.1);
+ //int verticalMargin = (int) (canvas.getHeight()*0.1);
+ int verticalMargin = horizontalMargin;
+ canvas.drawBitmap(bmp, new Rect(0, 0, bmp.getWidth(), bmp.getHeight()),
+ new Rect(horizontalMargin,verticalMargin,canvas.getWidth()-horizontalMargin,
+ canvas.getHeight()-verticalMargin),
+ mPaintBlack);//
+ }
+ if( bmp == null)
+ canvas.drawText(getContext().getString(R.string.bmp_null), 100, 100, new Paint());
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/ui/RecentFile.java b/android/source/src/java/org/libreoffice/ui/RecentFile.java
new file mode 100644
index 000000000..fdcc688aa
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/ui/RecentFile.java
@@ -0,0 +1,25 @@
+package org.libreoffice.ui;
+
+import android.net.Uri;
+
+/**
+ * An entry for a recently used file in the RecentFilesAdapter.
+ */
+public class RecentFile {
+
+ private final Uri uri;
+ private final String displayName;
+
+ public RecentFile(Uri docUri, String name) {
+ uri = docUri;
+ displayName = name;
+ }
+
+ public Uri getUri() {
+ return uri;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+}
diff --git a/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java b/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java
new file mode 100644
index 000000000..ef00b9fb6
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java
@@ -0,0 +1,93 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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.ui;
+
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.libreoffice.R;
+
+import java.util.List;
+
+class RecentFilesAdapter extends RecyclerView.Adapter<RecentFilesAdapter.ViewHolder> {
+
+ private final LibreOfficeUIActivity mActivity;
+ private final List<RecentFile> recentFiles;
+
+ RecentFilesAdapter(LibreOfficeUIActivity activity, List<RecentFile> recentFiles) {
+ this.mActivity = activity;
+ this.recentFiles = recentFiles;
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View item = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.item_recent_files, parent, false);
+ return new ViewHolder(item);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ final RecentFile entry = recentFiles.get(position);
+
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mActivity.openDocument(entry.getUri());
+ }
+ });
+
+ final String filename = entry.getDisplayName();
+ holder.textView.setText(filename);
+
+ int compoundDrawableInt = 0;
+
+ switch (FileUtilities.getType(filename)) {
+ case FileUtilities.DOC:
+ compoundDrawableInt = R.drawable.writer;
+ break;
+ case FileUtilities.CALC:
+ compoundDrawableInt = R.drawable.calc;
+ break;
+ case FileUtilities.DRAWING:
+ compoundDrawableInt = R.drawable.draw;
+ break;
+ case FileUtilities.IMPRESS:
+ compoundDrawableInt = R.drawable.impress;
+ break;
+ }
+
+ // set icon if known filetype was detected
+ if (compoundDrawableInt != 0)
+ holder.imageView.setImageDrawable(ContextCompat.getDrawable(mActivity, compoundDrawableInt));
+ }
+
+ @Override
+ public int getItemCount() {
+ return recentFiles.size();
+ }
+
+ class ViewHolder extends RecyclerView.ViewHolder {
+
+ TextView textView;
+ ImageView imageView;
+
+ ViewHolder(View itemView) {
+ super(itemView);
+ this.textView = itemView.findViewById(R.id.textView);
+ this.imageView = itemView.findViewById(R.id.imageView);
+ }
+ }
+}