Android: Abstract file management from LibreOfficeUIActivity.
This is the first step towards implementing support for different
cloud providers.
The use of File objects is replaced with the interface IFile, which
has similar operations. A LocalFile implementation is provided to
deal with local contents in the same way it was being done before.
Some system-wide storage operations are abstracted in the interface
IDocumentProvider. A LocalDocumentsProvider implementation is
provided.
Known issues in this patch:
* Dummy filesystem code has been removed. This should be provided as
an implementation of IDocumentProvider in case we need it, but that
will probably not happen.
* Sorting is not implemented in LocalDocumentsProvider yet. It seemed
not to be working anyway.
* Code to get directory thumbnails has been commented out. This code
will probably belong to the IDocumentProvider/IFile implementations.
We might want to have a different approach instead of reading
hidden thumbnail files, something similar to what the native
Start Center does.
Change-Id: Ib0882c69a0b24e28d2346bbe0154db01d1102b06
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/IDocumentProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/IDocumentProvider.java
new file mode 100644
index 0000000..bf50523
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/IDocumentProvider.java
@@ -0,0 +1,36 @@
/* -*- 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.storage;
import java.net.URI;
/**
* Represents a Document Provider, an object able to provide documents from a
* certain source (e.g. local documents, DropBox, Google Docs).
*/
public interface IDocumentProvider {
/**
* Provides the content root element for the Document Provider.
*
* @return Content root element.
*/
IFile getRootDirectory();
/**
* Transforms some URI into the IFile object that represents that content.
*
* @param uri
* URI pointing to some content object that has been previously
* retrieved with IFile.getUri().
* @return IFile object pointing to the content represented by uri.
*/
IFile createFromUri(URI uri);
}
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/IFile.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/IFile.java
new file mode 100644
index 0000000..5b71c09
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/IFile.java
@@ -0,0 +1,102 @@
/* -*- 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.storage;
import java.io.File;
import java.io.FileFilter;
import java.net.URI;
import java.util.Date;
import java.util.List;
/**
* An abstraction of the File class, intended to be implemented by different
* Document Providers.
*
* It represents a file or a directory in the context of a certain Document
* Provider. It wraps the file-related operations and provides access to the
* final document as a local File, downloading it if necessary.
*/
public interface IFile {
/**
* Provides a URI that represents this IFile object.
*
* @return URI that represents this IFile object in the context of the
* Document Provider that created it. The URI can be transformed
* back into an IFile object with IDocumentProvider.createFromUri().
*/
URI getUri();
/**
* Returns the name of the file or directory represented by this file.
*
* @return This file's name.
*/
String getName();
/**
* Indicates if this file represents a directory in the context of the
* Document Provider which originated it.
*
* @return true if this file is a directory, false otherwise.
*/
boolean isDirectory();
/**
* Returns the file size in bytes.
*
* @return file size in bytes, 0 if the file does not exist.
*/
long getSize();
/**
* Returns the time when this file was last modified, measured in
* milliseconds since January 1st, 1970, midnight.
*
* @return time when this file was last modified, or 0 if the file does not
* exist.
*/
Date getLastModified();
/**
* Returns a list containing the files in the directory represented by this
* file.
*
* @return list of files contained by this directory, or an empty list if
* this is not a directory.
*/
List<IFile> listFiles();
/**
* Gets the list of files contained in the directory represented by this
* file, and filters it through some FilenameFilter.
*
* @param filter
* the filter to match names against.
* @return filtered list of files contained by this directory, or an empty
* list if this is not a directory.
*/
List<IFile> listFiles(FileFilter filter);
/**
* Returns the pparent of this file.
*
* @return this file's parent or null if it does not have it.
*/
IFile getParent();
/**
* Returns the document wrapped by this IFile as a local file. The result
* for a directory is not defined.
*
* @return local file containing the document wrapped by this object.
*/
File getDocument();
}
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/local/LocalDocumentsProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/local/LocalDocumentsProvider.java
new file mode 100644
index 0000000..8e21182
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/local/LocalDocumentsProvider.java
@@ -0,0 +1,33 @@
/* -*- 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.storage.local;
import java.net.URI;
import org.libreoffice.storage.IDocumentProvider;
import org.libreoffice.storage.IFile;
import android.os.Environment;
/**
* Implementation of IDocumentProvider for the local file system.
*/
public class LocalDocumentsProvider implements IDocumentProvider {
@Override
public IFile getRootDirectory() {
return new LocalFile(Environment.getExternalStorageDirectory());
}
@Override
public IFile createFromUri(URI uri) {
return new LocalFile(uri);
}
}
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/local/LocalFile.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/local/LocalFile.java
new file mode 100644
index 0000000..797d909
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/local/LocalFile.java
@@ -0,0 +1,86 @@
/* -*- 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.storage.local;
import java.io.File;
import java.io.FileFilter;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.libreoffice.storage.IFile;
/**
* Implementation of IFile for the local file system.
*/
public class LocalFile implements IFile {
private File file;
public LocalFile(File file) {
this.file = file;
}
public LocalFile(URI uri) {
this.file = new File(uri);
}
public URI getUri() {
return file.toURI();
}
public String getName() {
return file.getName();
}
@Override
public boolean isDirectory() {
return file.isDirectory();
}
@Override
public long getSize() {
return file.length();
}
@Override
public Date getLastModified() {
return new Date(file.lastModified());
}
@Override
public List<IFile> listFiles() {
List<IFile> children = new ArrayList<IFile>();
for (File child : file.listFiles()) {
children.add(new LocalFile(child));
}
return children;
}
@Override
public List<IFile> listFiles(FileFilter filter) {
List<IFile> children = new ArrayList<IFile>();
for (File child : file.listFiles(filter)) {
children.add(new LocalFile(child));
}
return children;
}
@Override
public IFile getParent() {
return new LocalFile(file.getParentFile());
}
@Override
public File getDocument() {
return file;
}
}
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/GridItemAdapter.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/GridItemAdapter.java
index d0470e7..64eebc1 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/GridItemAdapter.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/GridItemAdapter.java
@@ -10,11 +10,13 @@
package org.libreoffice.ui;
import org.libreoffice.R;
import org.libreoffice.storage.IFile;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.List;
import android.content.Context;
import android.util.Log;
@@ -33,25 +35,26 @@ import android.graphics.Color;
public class GridItemAdapter extends BaseAdapter {
Context mContext;
File[] filePaths;
File currentDirectory;
List<IFile> filePaths;
IFile currentDirectory;
String TAG = "GridItemAdapter";
public GridItemAdapter(Context mContext, File[] filePaths) {
public GridItemAdapter(Context mContext, List<IFile> filePaths) {
this.mContext = mContext;
this.filePaths = filePaths;
for(File fn : filePaths){
for (IFile fn : filePaths) {
Log.d(TAG, fn.getName());
}
}
public GridItemAdapter(Context mContext, File currentDirectory) {
public GridItemAdapter(Context mContext, IFile currentDirectory) {
this.mContext = mContext;
this.currentDirectory = currentDirectory;
filePaths = currentDirectory.listFiles();
}
public GridItemAdapter(Context mContext, File currentDirectory, File[] filteredFiles)
public GridItemAdapter(Context mContext, IFile currentDirectory,
List<IFile> filteredFiles)
{
this.mContext = mContext;
this.currentDirectory = currentDirectory;
@@ -59,7 +62,7 @@ public class GridItemAdapter extends BaseAdapter {
}
public int getCount() {
return filePaths.length;
return filePaths.size();
}
public Object getItem(int position) {
@@ -90,11 +93,11 @@ public class GridItemAdapter extends BaseAdapter {
// set value into textview
TextView textView = (TextView) gridView
.findViewById(R.id.grid_item_label);
textView.setText(filePaths[position].getName());
textView.setText(filePaths.get(position).getName());
// set image based on selected text
ImageView imageView = (ImageView) gridView
.findViewById(R.id.grid_item_image);
if( filePaths[position].isDirectory() ) // Is a folder
if (filePaths.get(position).isDirectory()) // Is a folder
{
// Default view is a generic folder icon.
imageView.setImageResource(R.drawable.folder);
@@ -102,13 +105,14 @@ public class GridItemAdapter extends BaseAdapter {
gridView = inflater.inflate(R.layout.file_explorer_folder_icon, null);
org.libreoffice.ui.FolderIconView icon =
(org.libreoffice.ui.FolderIconView)gridView.findViewById(R.id.folder_icon);
icon.setDir( filePaths[position]);
// icon.setDir( filePaths[position]);
textView = (TextView) gridView.findViewById(R.id.grid_item_label);
textView.setText(filePaths[position].getName());
textView.setText(filePaths.get(position).getName());
return gridView;
}
else
{
/*
File thumbnailFile = new File( filePaths[position].getParent() , "."
+ filePaths[position].getName().split("[.]")[0] + ".png");
BitmapFactory factory = new BitmapFactory();
@@ -118,13 +122,16 @@ public class GridItemAdapter extends BaseAdapter {
}else{
Log.i( "GRID" , thumbnailFile.getAbsolutePath() );
}
switch (FileUtilities.getType(filePaths[position].getName()))
*/
switch (FileUtilities.getType(filePaths.get(position).getName()))
{
case FileUtilities.DOC:
/*
if( thumb != null){
imageView.setImageBitmap( thumb );
break;
}
*/
imageView.setImageResource(R.drawable.writer);
break;
/*case FileUtilities.CALC:
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
index 0c9668d..8bb64f3 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
@@ -12,12 +12,17 @@ package org.libreoffice.ui;
import org.libreoffice.R;
import org.libreoffice.LOAbout;
import org.libreoffice.android.Bootstrap;
import org.libreoffice.storage.IDocumentProvider;
import org.libreoffice.storage.IFile;
import org.libreoffice.storage.local.LocalDocumentsProvider;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.prefs.Preferences;
import android.graphics.drawable.BitmapDrawable;
@@ -58,17 +63,22 @@ import android.widget.ListView;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import java.net.URI;
import java.net.URISyntaxException;
public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNavigationListener {
private String tag = "file_manager";
private SharedPreferences prefs;
private File homeDirectory;
private File currentDirectory;
private int filterMode = FileUtilities.ALL;
private int viewMode;
private int sortMode;
FileFilter fileFilter;
private File[] filePaths;
FilenameFilter filenameFilter;
private List<IFile> filePaths;
private IDocumentProvider documentProvider = new LocalDocumentsProvider();
private IFile homeDirectory;
private IFile currentDirectory;
private static final String CURRENT_DIRECTORY_KEY = "CURRENT_DIRECTORY";
private static final String FILTER_MODE_KEY = "FILTER_MODE";
@@ -92,7 +102,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
super.onCreate(savedInstanceState);
Log.d(tag, "onCreate - tweaked - meeks !");
//Set the "home" - top level - directory.
homeDirectory = Environment.getExternalStorageDirectory();
homeDirectory = documentProvider.getRootDirectory();
currentDirectory = homeDirectory;
//Load default settings
@@ -135,7 +145,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
// code to make a grid view
setContentView(R.layout.file_grid);
gv = (GridView)findViewById(R.id.file_explorer_grid_view);
filePaths = currentDirectory.listFiles( FileUtilities.getFileFilter( filterMode ) );
filePaths = currentDirectory.listFiles(FileUtilities.getFileFilter(filterMode));
gv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
@@ -149,7 +159,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
setContentView(R.layout.file_list);
lv = (ListView)findViewById( R.id.file_explorer_list_view);
lv.setClickable(true);
filePaths = currentDirectory.listFiles( FileUtilities.getFileFilter( filterMode ) );
filePaths = currentDirectory.listFiles(FileUtilities.getFileFilter(filterMode));
lv.setAdapter( new ListItemAdapter(getApplicationContext(), filePaths) );
actionBar.setSelectedNavigationItem( filterMode + 1 );
registerForContextMenu(lv);
@@ -181,7 +191,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
}
}
public void openDirectory(File dir ){
public void openDirectory(IFile dir) {
currentDirectory = dir;
if( !currentDirectory.equals( homeDirectory )){
ActionBar actionBar = getActionBar();
@@ -190,8 +200,8 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled( false );
}
filePaths = currentDirectory.listFiles( FileUtilities.getFileFilter( filterMode ) );
FileUtilities.sortFiles( filePaths, sortMode );
filePaths = currentDirectory.listFiles(FileUtilities.getFileFilter(filterMode));
// FileUtilities.sortFiles( filePaths, sortMode );
/*
for( int i = 0; i < fileNames.length; i++){
fileNames[ i ] = filePaths[ i ].getName();
@@ -208,7 +218,8 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
}
}
public void open(File file) {
public void open(IFile document) {
File file = document.getDocument();
Intent i = new Intent(Intent.ACTION_VIEW, Uri.fromFile(file));
i.setComponent(new ComponentName(
"org.libreoffice",
@@ -217,7 +228,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
}
private void open(int position) {
File file = filePaths[position];
IFile file = filePaths.get(position);
if (!file.isDirectory()) {
open(file);
} else {
@@ -226,7 +237,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
}
private void share(int position) {
File file = filePaths[position];
File file = filePaths.get(position).getDocument();
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
Uri uri = Uri.fromFile(file);
String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
@@ -259,7 +270,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
switch (item.getItemId()) {
case android.R.id.home:
if( !currentDirectory.equals( homeDirectory ) ){
openDirectory( currentDirectory.getParentFile() );
openDirectory(currentDirectory.getParent());
}
break;
case R.id.menu_view_toggle:
@@ -336,7 +347,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
outState.putString( CURRENT_DIRECTORY_KEY , currentDirectory.getAbsolutePath() );
outState.putString(CURRENT_DIRECTORY_KEY, currentDirectory.getUri().toString());
outState.putInt( FILTER_MODE_KEY , filterMode );
outState.putInt( EXPLORER_VIEW_TYPE_KEY , viewMode );
@@ -352,7 +363,12 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
if( savedInstanceState.isEmpty() ){
return;
}
currentDirectory = new File( savedInstanceState.getString( CURRENT_DIRECTORY_KEY ) );
try {
currentDirectory = documentProvider.createFromUri(new URI(
savedInstanceState.getString(CURRENT_DIRECTORY_KEY)));
} catch (URISyntaxException e) {
currentDirectory = documentProvider.getRootDirectory();
}
filterMode = savedInstanceState.getInt( FILTER_MODE_KEY , FileUtilities.ALL ) ;
viewMode = savedInstanceState.getInt( EXPLORER_VIEW_TYPE_KEY , GRID_VIEW );
//openDirectory( currentDirectory );
@@ -374,7 +390,12 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
readPreferences();// intent values take precedence over prefs?
Intent i = this.getIntent();
if( i.hasExtra( CURRENT_DIRECTORY_KEY ) ){
currentDirectory = new File( i.getStringExtra( CURRENT_DIRECTORY_KEY ) );
try {
currentDirectory = documentProvider.createFromUri(new URI(
i.getStringExtra(CURRENT_DIRECTORY_KEY)));
} catch (URISyntaxException e) {
currentDirectory = documentProvider.getRootDirectory();
}
Log.d(tag, CURRENT_DIRECTORY_KEY);
}
if( i.hasExtra( FILTER_MODE_KEY ) ){
@@ -423,18 +444,17 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
class ListItemAdapter implements ListAdapter{
private Context mContext;
private File[] filePaths;
private List<IFile> filePaths;
private final long KB = 1024;
private final long MB = 1048576;
public ListItemAdapter(Context mContext, File[] filePaths) {
public ListItemAdapter(Context mContext, List<IFile> filePaths) {
this.mContext = mContext;
this.filePaths = filePaths;
}
public int getCount() {
// TODO Auto-generated method stub
return filePaths.length;
return filePaths.size();
}
public Object getItem(int arg0) {
@@ -487,13 +507,13 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
// set value into textview
TextView filename = (TextView) listItem.findViewById(R.id.file_list_item_name);
filename.setText( filePaths[ position ].getName() );
filename.setText(filePaths.get(position).getName());
//filename.setClickable(true);
TextView fileSize = (TextView) listItem.findViewById(R.id.file_list_item_size);
//TODO Give size in KB , MB as appropriate.
String size = "0B";
long length = filePaths[ position ].length();
long length = filePaths.get(position).getSize();
if( length < KB ){
size = Long.toString( length ) + "B";
}
@@ -508,13 +528,13 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
TextView fileDate = (TextView) listItem.findViewById(R.id.file_list_item_date);
SimpleDateFormat df = new SimpleDateFormat("dd MMM yyyy hh:ss");
Date date = new Date( filePaths[ position ].lastModified() );
Date date = filePaths.get(position).getLastModified();
//TODO format date
fileDate.setText( df.format( date ) );
// set image based on selected text
ImageView imageView = (ImageView) listItem.findViewById(R.id.file_list_item_icon);
switch (FileUtilities.getType(filePaths[position].getName()))
switch (FileUtilities.getType(filePaths.get(position).getName()))
{
case FileUtilities.DOC:
imageView.setImageResource(R.drawable.writer);
@@ -531,7 +551,7 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
default:
break;
}
if( filePaths[position].isDirectory() ){
if (filePaths.get(position).isDirectory()) {
//Eventually have thumbnails of each sub file on a black circle
//For now just a folder icon
imageView.setImageResource(R.drawable.folder);