diff --git a/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java b/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java index 2c101b08..2894d73e 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java +++ b/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java @@ -21,7 +21,8 @@ public class MainApplication extends Application { ApplicationContext.getInstance().setUserInfo(getApplicationContext(), json); // TODO Fullscreen preview - // TODO Files adding/deleting + // TODO Event on file uploaded to refresh file list + // TODO Files deleting super.onCreate(); } diff --git a/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java b/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java index 26575b6d..66508ec7 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java +++ b/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java @@ -3,10 +3,12 @@ package com.sismics.docs.activity; import android.app.AlertDialog; import android.app.DownloadManager; import android.app.ProgressDialog; +import android.content.ClipData; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.support.v4.app.DialogFragment; @@ -42,7 +44,9 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import de.greenrobot.event.EventBus; @@ -392,10 +396,35 @@ public class DocumentViewActivity extends ActionBarActivity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (document == null) return; + if (requestCode == REQUEST_CODE_ADD_FILE && resultCode == RESULT_OK) { - Intent intent = new Intent(this, FileUploadService.class) - .putExtra(FileUploadService.PARAM_URI, data.getData()); - startService(intent); + List uriList = new ArrayList<>(); + // Single file upload + if (data.getData() != null) { + uriList.add(data.getData()); + } + + // Handle multiple file upload + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + ClipData clipData = data.getClipData(); + if (clipData != null) { + for (int i = 0; i < clipData.getItemCount(); ++i) { + Uri uri = clipData.getItemAt(i).getUri(); + if (uri != null) { + uriList.add(uri); + } + } + } + } + + // Upload all files + for (Uri uri : uriList) { + Intent intent = new Intent(this, FileUploadService.class) + .putExtra(FileUploadService.PARAM_URI, uri) + .putExtra(FileUploadService.PARAM_DOCUMENT_ID, document.optString("id")); + startService(intent); + } } } diff --git a/docs-android/app/src/main/java/com/sismics/docs/resource/BaseResource.java b/docs-android/app/src/main/java/com/sismics/docs/resource/BaseResource.java index 7f64126d..d79d8ef7 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/resource/BaseResource.java +++ b/docs-android/app/src/main/java/com/sismics/docs/resource/BaseResource.java @@ -36,12 +36,12 @@ public class BaseResource { /** * User-Agent to use. */ - private static String USER_AGENT = null; + protected static String USER_AGENT = null; /** * Accept-Language header. */ - private static String ACCEPT_LANGUAGE = null; + protected static String ACCEPT_LANGUAGE = null; /** * HTTP client. @@ -69,8 +69,7 @@ public class BaseResource { * @param context Context */ protected static void init(Context context) { - PersistentCookieStore cookieStore = new PersistentCookieStore(context); - client.setCookieStore(cookieStore); + client.setCookieStore(new PersistentCookieStore(context)); if (USER_AGENT == null) { USER_AGENT = "Sismics Docs Android " + ApplicationUtil.getVersionName(context) + "/Android " + Build.VERSION.RELEASE + "/" + Build.MODEL; diff --git a/docs-android/app/src/main/java/com/sismics/docs/resource/FileResource.java b/docs-android/app/src/main/java/com/sismics/docs/resource/FileResource.java index c30cf3fd..1f7e4331 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/resource/FileResource.java +++ b/docs-android/app/src/main/java/com/sismics/docs/resource/FileResource.java @@ -2,8 +2,14 @@ package com.sismics.docs.resource; import android.content.Context; +import com.loopj.android.http.PersistentCookieStore; +import com.loopj.android.http.RequestParams; +import com.loopj.android.http.SyncHttpClient; import com.sismics.docs.listener.JsonHttpResponseHandler; +import java.io.InputStream; +import java.security.KeyStore; + /** * Access to /file API. @@ -23,4 +29,32 @@ public class FileResource extends BaseResource { client.get(getApiUrl(context) + "/file/list?id=" + documentId, responseHandler); } + + /** + * PUT /file. + * + * @param context Context + * @param documentId Document ID + * @param is Input stream + * @param responseHandler Callback + * @throws Exception + */ + public static void addSync(Context context, String documentId, InputStream is, JsonHttpResponseHandler responseHandler) throws Exception { + init(context); + + SyncHttpClient client = new SyncHttpClient(); + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + MySSLSocketFactory sf = new MySSLSocketFactory(trustStore); + sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + client.setSSLSocketFactory(sf); + client.setCookieStore(new PersistentCookieStore(context)); + client.setUserAgent(USER_AGENT); + client.addHeader("Accept-Language", ACCEPT_LANGUAGE); + + RequestParams params = new RequestParams(); + params.put("id", documentId); + params.put("file", is, "file", "application/octet-stream", true); + client.put(getApiUrl(context) + "/file", params, responseHandler); + } } diff --git a/docs-android/app/src/main/java/com/sismics/docs/service/FileUploadService.java b/docs-android/app/src/main/java/com/sismics/docs/service/FileUploadService.java index 34758d55..b0a13214 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/service/FileUploadService.java +++ b/docs-android/app/src/main/java/com/sismics/docs/service/FileUploadService.java @@ -11,6 +11,11 @@ import android.support.v4.app.NotificationCompat.Builder; import android.util.Log; import com.sismics.docs.R; +import com.sismics.docs.listener.JsonHttpResponseHandler; +import com.sismics.docs.resource.FileResource; + +import org.apache.http.Header; +import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; @@ -26,6 +31,7 @@ public class FileUploadService extends IntentService { private static final int UPLOAD_NOTIFICATION_ID = 1; private static final int UPLOAD_NOTIFICATION_ID_DONE = 2; public static final String PARAM_URI = "uri"; + public static final String PARAM_DOCUMENT_ID = "documentId"; private NotificationManager notificationManager; private Builder notification; @@ -54,7 +60,7 @@ public class FileUploadService extends IntentService { wakeLock.acquire(); try { onStart(); - handleFileUpload((Uri) intent.getParcelableExtra(PARAM_URI)); + handleFileUpload(intent.getStringExtra(PARAM_DOCUMENT_ID), (Uri) intent.getParcelableExtra(PARAM_URI)); } catch (Exception e) { Log.e(TAG, "Error uploading the file", e); onError(); @@ -66,24 +72,23 @@ public class FileUploadService extends IntentService { /** * Actually uploading the file. * + * @param documentId Document ID * @param uri Data URI * @throws IOException */ - private void handleFileUpload(final Uri uri) throws IOException { - InputStream is = null; - try { - is = getContentResolver().openInputStream(uri); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // Ignore - } + private void handleFileUpload(final String documentId, final Uri uri) throws Exception { + final InputStream is = getContentResolver().openInputStream(uri); + FileResource.addSync(this, documentId, is, new JsonHttpResponseHandler() { + @Override + public void onSuccess(int statusCode, Header[] headers, JSONObject response) { + FileUploadService.this.onComplete(); } - } - onComplete(); + @Override + public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { + FileUploadService.this.onError(); + } + }); } /** @@ -93,28 +98,13 @@ public class FileUploadService extends IntentService { notification.setContentTitle(getString(R.string.upload_notification_title)) .setContentText(getString(R.string.upload_notification_message)) .setContentIntent(PendingIntent.getBroadcast(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT)) - .setSmallIcon(R.drawable.ic_launcher) + .setSmallIcon(R.drawable.ic_file_upload_white_24dp) .setProgress(100, 0, true) .setOngoing(true); startForeground(UPLOAD_NOTIFICATION_ID, notification.build()); } - /** - * On upload progress. - * - * @param progress Progression (100 based) - */ - private void onProgress(final int progress) { - notification.setContentTitle(getString(R.string.upload_notification_title)) - .setContentText(getString(R.string.upload_notification_message)) - .setSmallIcon(R.drawable.ic_launcher) - .setProgress(100, progress, false) - .setOngoing(true); - - startForeground(UPLOAD_NOTIFICATION_ID, notification.build()); - } - /** * On upload complete. */ @@ -130,7 +120,7 @@ public class FileUploadService extends IntentService { notification.setContentTitle(getString(R.string.upload_notification_title)) .setContentText(getString(R.string.upload_notification_error)) - .setSmallIcon(R.drawable.ic_launcher) + .setSmallIcon(R.drawable.ic_file_upload_white_24dp) .setProgress(0, 0, false) .setOngoing(false); diff --git a/docs-android/app/src/main/res/values/strings.xml b/docs-android/app/src/main/res/values/strings.xml index 853ce09d..bb24aecc 100644 --- a/docs-android/app/src/main/res/values/strings.xml +++ b/docs-android/app/src/main/res/values/strings.xml @@ -85,9 +85,8 @@ Network error while deleting this document Deleting document Error while reading the file - Adding a file + Sismics Docs Uploading the new file to the document - File upload completed Error uploading the new file