Kaydet (Commit) c28e9fd0 authored tarafından Jacobo Aragunde Pérez's avatar Jacobo Aragunde Pérez Kaydeden (comit) Tomaž Vajngerl

Android: Implement cloud save

The LOMainActivity now needs to be aware of Document Providers, so we
pass the providerId and documentUri in the Intent so it can rebuild
the DocumentProvider and the IFile objects.

We also implement the ownCloud save operation.

TODO: since the local save operation does not have a callback, we do
not know when the cloud save operation should be performed. Now we
just wait 5 seconds to trigger it.

Change-Id: I060969e12888eca07c8c56ddc82cbed6c45a0739
(cherry picked from commit 626ebde4)
üst f550e1f0
package org.libreoffice; package org.libreoffice;
import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
...@@ -21,6 +23,8 @@ import android.widget.ListView; ...@@ -21,6 +23,8 @@ import android.widget.ListView;
import android.widget.Toast; import android.widget.Toast;
import org.libreoffice.overlay.DocumentOverlay; import org.libreoffice.overlay.DocumentOverlay;
import org.libreoffice.storage.DocumentProviderFactory;
import org.libreoffice.storage.IFile;
import org.mozilla.gecko.ZoomConstraints; import org.mozilla.gecko.ZoomConstraints;
import org.mozilla.gecko.gfx.GeckoLayerClient; import org.mozilla.gecko.gfx.GeckoLayerClient;
import org.mozilla.gecko.gfx.LayerView; import org.mozilla.gecko.gfx.LayerView;
...@@ -31,6 +35,7 @@ import java.io.FileOutputStream; ...@@ -31,6 +35,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -50,13 +55,16 @@ public class LibreOfficeMainActivity extends ActionBarActivity { ...@@ -50,13 +55,16 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
private static boolean mEnableEditing; private static boolean mEnableEditing;
int providerId;
URI documentUri;
public Handler mMainHandler; public Handler mMainHandler;
private DrawerLayout mDrawerLayout; private DrawerLayout mDrawerLayout;
private ListView mDrawerList; private ListView mDrawerList;
private List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>(); private List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>();
private DocumentPartViewListAdapter mDocumentPartViewListAdapter; private DocumentPartViewListAdapter mDocumentPartViewListAdapter;
private String mInputFile; private File mInputFile;
private DocumentOverlay mDocumentOverlay; private DocumentOverlay mDocumentOverlay;
private File mTempFile = null; private File mTempFile = null;
private LOAbout mAbout; private LOAbout mAbout;
...@@ -110,8 +118,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity { ...@@ -110,8 +118,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
mAbout.showAbout(); mAbout.showAbout();
return true; return true;
case R.id.action_save: case R.id.action_save:
Toast.makeText(this, "Saving the document...", Toast.LENGTH_SHORT).show(); saveDocument();
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Save"));
return true; return true;
case R.id.action_parts: case R.id.action_parts:
mDrawerLayout.openDrawer(mDrawerList); mDrawerLayout.openDrawer(mDrawerList);
...@@ -154,17 +161,23 @@ public class LibreOfficeMainActivity extends ActionBarActivity { ...@@ -154,17 +161,23 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
if (getIntent().getData() != null) { if (getIntent().getData() != null) {
if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_CONTENT)) { if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
if (copyFileToTemp() && mTempFile != null) { if (copyFileToTemp() && mTempFile != null) {
mInputFile = mTempFile.getPath(); mInputFile = mTempFile;
Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath()); Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath());
} else { } else {
// TODO: can't open the file // TODO: can't open the file
} }
} else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) { } else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) {
mInputFile = getIntent().getData().getPath(); mInputFile = new File(getIntent().getData().getPath());
Log.d(LOGTAG, "SCHEME_FILE: getPath(): " + getIntent().getData().getPath()); Log.d(LOGTAG, "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 { } else {
mInputFile = DEFAULT_DOC_PATH; mInputFile = new File(DEFAULT_DOC_PATH);
} }
toolbar.setNavigationOnClickListener(new View.OnClickListener() { toolbar.setNavigationOnClickListener(new View.OnClickListener() {
...@@ -238,6 +251,50 @@ public class LibreOfficeMainActivity extends ActionBarActivity { ...@@ -238,6 +251,50 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
return false; return false;
} }
/**
* Save the document and invoke save on document provider to upload the file
* to the cloud if necessary.
*/
private void saveDocument() {
Toast.makeText(this, "Saving the document...", Toast.LENGTH_SHORT).show();
// local save
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Save"));
final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
// rebuild the IFile object from the data passed in the Intent
IFile mStorageFile = DocumentProviderFactory.getInstance()
.getProvider(providerId).createFromUri(documentUri);
// call document provider save operation
mStorageFile.saveDocument(mInputFile);
}
catch (final RuntimeException e) {
final Activity activity = LibreOfficeMainActivity.this;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity, e.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
Log.e(LOGTAG, e.getMessage(), e.getCause());
}
return null;
}
};
// Delay the call to document provider save operation to ensure the local
// file has been saved.
// FIXME: horrible hack, ideally the save operation should have a callback
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
task.execute();
}
}, 5000);
}
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
...@@ -260,7 +317,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity { ...@@ -260,7 +317,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
protected void onStart() { protected void onStart() {
Log.i(LOGTAG, "onStart.."); Log.i(LOGTAG, "onStart..");
super.onStart(); super.onStart();
LOKitShell.sendLoadEvent(mInputFile); LOKitShell.sendLoadEvent(mInputFile.getPath());
} }
@Override @Override
......
...@@ -102,4 +102,12 @@ public interface IFile { ...@@ -102,4 +102,12 @@ public interface IFile {
* @throws RuntimeException in case of error. * @throws RuntimeException in case of error.
*/ */
File getDocument(); File getDocument();
/**
* Replaces the wrapped document with a new version of it.
*
* @param file
* A local file pointing to the new version of the document.
*/
void saveDocument(File file);
} }
...@@ -93,4 +93,9 @@ public class LocalFile implements IFile { ...@@ -93,4 +93,9 @@ public class LocalFile implements IFile {
LocalFile file = (LocalFile) object; LocalFile file = (LocalFile) object;
return file.getUri().equals(getUri()); return file.getUri().equals(getUri());
} }
@Override
public void saveDocument(File file) {
// do nothing; file is local
}
} }
...@@ -9,10 +9,14 @@ import java.util.List; ...@@ -9,10 +9,14 @@ import java.util.List;
import org.libreoffice.storage.IFile; import org.libreoffice.storage.IFile;
import android.util.Log;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.files.ChunkedUploadRemoteFileOperation;
import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation; import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation; import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
import com.owncloud.android.lib.resources.files.RemoteFile; import com.owncloud.android.lib.resources.files.RemoteFile;
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
/** /**
* Implementation of IFile for ownCloud servers. * Implementation of IFile for ownCloud servers.
...@@ -119,4 +123,22 @@ public class OwnCloudFile implements IFile { ...@@ -119,4 +123,22 @@ public class OwnCloudFile implements IFile {
OwnCloudFile file = (OwnCloudFile) object; OwnCloudFile file = (OwnCloudFile) object;
return file.getUri().equals(getUri()); return file.getUri().equals(getUri());
} }
@Override
public void saveDocument(File newFile) {
UploadRemoteFileOperation uploadOperation;
if (newFile.length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE) {
uploadOperation = new ChunkedUploadRemoteFileOperation(
newFile.getPath(), file.getRemotePath(), file.getMimeType());
} else {
uploadOperation = new UploadRemoteFileOperation(newFile.getPath(),
file.getRemotePath(), file.getMimeType());
}
RemoteOperationResult result = uploadOperation.execute(provider
.getClient());
if (!result.isSuccess()) {
throw provider.buildRuntimeExceptionForResultCode(result.getCode());
}
}
} }
...@@ -351,7 +351,7 @@ public class LibreOfficeUIActivity extends ActionBarActivity implements ActionBa ...@@ -351,7 +351,7 @@ public class LibreOfficeUIActivity extends ActionBarActivity implements ActionBa
}.execute(dir); }.execute(dir);
} }
public void open(IFile document) { public void open(final IFile document) {
new AsyncTask<IFile, Void, File>() { new AsyncTask<IFile, Void, File>() {
@Override @Override
protected File doInBackground(IFile... document) { protected File doInBackground(IFile... document) {
...@@ -382,6 +382,13 @@ public class LibreOfficeUIActivity extends ActionBarActivity implements ActionBa ...@@ -382,6 +382,13 @@ public class LibreOfficeUIActivity extends ActionBarActivity implements ActionBa
ComponentName componentName = new ComponentName(packageName, ComponentName componentName = new ComponentName(packageName,
LibreOfficeMainActivity.class.getName()); LibreOfficeMainActivity.class.getName());
i.setComponent(componentName); i.setComponent(componentName);
// these extras allow to rebuild the IFile object in LOMainActivity
i.putExtra("org.libreoffice.document_provider_id",
documentProvider.getId());
i.putExtra("org.libreoffice.document_uri",
document.getUri());
startActivity(i); startActivity(i);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment