package org.wordpress.android.ui.media; import android.app.Activity; import android.app.Fragment; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.graphics.BitmapFactory; import android.net.ConnectivityManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.provider.MediaStore; import android.support.v4.content.CursorLoader; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import org.wordpress.android.BuildConfig; import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.models.Blog; import org.wordpress.android.models.MediaUploadState; import org.wordpress.android.ui.RequestCodes; import org.wordpress.android.ui.media.WordPressMediaUtils.LaunchCameraCallback; import org.wordpress.android.ui.media.services.MediaEvents.MediaChanged; import org.wordpress.android.ui.media.services.MediaUploadService; import org.wordpress.android.util.MediaUtils; import org.wordpress.android.util.NetworkUtils; import org.wordpress.android.util.helpers.MediaFile; import java.io.File; import java.util.List; import de.greenrobot.event.EventBus; /** * An invisible fragment in charge of launching the right intents to camera, video, and image library. * Also queues up media for upload and listens to notifications from the upload service. */ public class MediaAddFragment extends Fragment implements LaunchCameraCallback { private static final String BUNDLE_MEDIA_CAPTURE_PATH = "mediaCapturePath"; private String mMediaCapturePath = ""; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // This view doesn't really matter as this fragment is invisible if (savedInstanceState != null && savedInstanceState.getString(BUNDLE_MEDIA_CAPTURE_PATH) != null) mMediaCapturePath = savedInstanceState.getString(BUNDLE_MEDIA_CAPTURE_PATH); return inflater.inflate(R.layout.actionbar_add_media_cell, container, false); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (mMediaCapturePath != null && !mMediaCapturePath.equals("")) outState.putString(BUNDLE_MEDIA_CAPTURE_PATH, mMediaCapturePath); } @Override public void onStart() { super.onStart(); // register context for change in connection status getActivity().registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); } @Override public void onStop() { getActivity().unregisterReceiver(mReceiver); super.onStop(); } @Override public void onResume() { super.onResume(); resumeMediaUploadService(); } private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) { // Coming from zero connection. Re-register upload intent. resumeMediaUploadService(); } } }; @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (data != null || requestCode == RequestCodes.TAKE_PHOTO || requestCode == RequestCodes.TAKE_VIDEO) { String path; switch (requestCode) { case RequestCodes.PICTURE_LIBRARY: case RequestCodes.VIDEO_LIBRARY: Uri imageUri = data.getData(); fetchMedia(imageUri); break; case RequestCodes.TAKE_PHOTO: if (resultCode == Activity.RESULT_OK) { path = mMediaCapturePath; mMediaCapturePath = null; queueFileForUpload(path); } break; case RequestCodes.TAKE_VIDEO: if (resultCode == Activity.RESULT_OK) { path = getRealPathFromURI(MediaUtils.getLastRecordedVideoUri(getActivity())); queueFileForUpload(path); } break; } } } private void fetchMedia(Uri mediaUri) { if (!MediaUtils.isInMediaStore(mediaUri)) { // Create an AsyncTask to download the file new DownloadMediaTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mediaUri); } else { // It is a regular local media file String path = getRealPathFromURI(mediaUri); queueFileForUpload(path); } } private String getRealPathFromURI(Uri uri) { String path; if ("content".equals(uri.getScheme())) { path = getRealPathFromContentURI(uri); } else if ("file".equals(uri.getScheme())) { path = uri.getPath(); } else { path = uri.toString(); } return path; } private String getRealPathFromContentURI(Uri contentUri) { if (contentUri == null) return null; String[] proj = { MediaStore.Images.Media.DATA }; CursorLoader loader = new CursorLoader(getActivity(), contentUri, proj, null, null, null); Cursor cursor = loader.loadInBackground(); if (cursor == null) return null; int column_index = cursor.getColumnIndex(MediaStore.Images.Media.DATA); if (column_index == -1) { cursor.close(); return null; } String path; if (cursor.moveToFirst()) { path = cursor.getString(column_index); } else { path = null; } cursor.close(); return path; } private void queueFileForUpload(String path) { if (path == null || path.equals("")) { Toast.makeText(getActivity(), "Error opening file", Toast.LENGTH_SHORT).show(); return; } Blog blog = WordPress.getCurrentBlog(); File file = new File(path); if (!file.exists()) { return; } String mimeType = MediaUtils.getMediaFileMimeType(file); String fileName = MediaUtils.getMediaFileName(file, mimeType); MediaFile mediaFile = new MediaFile(); mediaFile.setBlogId(String.valueOf(blog.getLocalTableBlogId())); mediaFile.setFileName(fileName); mediaFile.setFilePath(path); mediaFile.setUploadState("queued"); mediaFile.setDateCreatedGMT(System.currentTimeMillis()); mediaFile.setMediaId(String.valueOf(System.currentTimeMillis())); if (mimeType != null && mimeType.startsWith("image")) { // get width and height BitmapFactory.Options bfo = new BitmapFactory.Options(); bfo.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, bfo); mediaFile.setWidth(bfo.outWidth); mediaFile.setHeight(bfo.outHeight); } if (!TextUtils.isEmpty(mimeType)) { mediaFile.setMimeType(mimeType); } WordPress.wpDB.saveMediaFile(mediaFile); EventBus.getDefault().post(new MediaChanged(String.valueOf(blog.getLocalTableBlogId()), mediaFile.getMediaId())); startMediaUploadService(); } private void startMediaUploadService() { if (NetworkUtils.isNetworkAvailable(getActivity())) { getActivity().startService(new Intent(getActivity(), MediaUploadService.class)); } } private void resumeMediaUploadService() { startMediaUploadService(); } @Override public void onMediaCapturePathReady(String mediaCapturePath) { mMediaCapturePath = mediaCapturePath; } public void launchCamera() { WordPressMediaUtils.launchCamera(this, BuildConfig.APPLICATION_ID, this); } public void launchVideoCamera() { WordPressMediaUtils.launchVideoCamera(this); } public void launchVideoLibrary() { WordPressMediaUtils.launchVideoLibrary(this); } public void launchPictureLibrary() { WordPressMediaUtils.launchPictureLibrary(this); } public void addToQueue(String mediaId) { String blogId = String.valueOf(WordPress.getCurrentBlog().getLocalTableBlogId()); WordPress.wpDB.updateMediaUploadState(blogId, mediaId, MediaUploadState.QUEUED); startMediaUploadService(); } public void uploadList(List<Uri> uriList) { for (Uri uri : uriList) { fetchMedia(uri); } } private class DownloadMediaTask extends AsyncTask<Uri, Integer, Uri> { @Override protected Uri doInBackground(Uri... uris) { Uri imageUri = uris[0]; return MediaUtils.downloadExternalMedia(getActivity(), imageUri); } protected void onPostExecute(Uri newUri) { if (getActivity() == null) return; if (newUri != null) { String path = getRealPathFromURI(newUri); queueFileForUpload(path); } else Toast.makeText(getActivity(), getString(R.string.error_downloading_image), Toast.LENGTH_SHORT).show(); } } }