blob: ea4664f6776a7eb24cc6fc58364a1ee835134ac2 [file] [log] [blame]
package org.wordpress.android.ui.media;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import com.android.volley.toolbox.ImageLoader;
import org.wordpress.android.BuildConfig;
import org.wordpress.android.R;
import org.wordpress.android.WordPress;
import org.wordpress.android.ui.RequestCodes;
import org.wordpress.android.util.MediaUtils;
import org.wordpress.android.widgets.WPViewPager;
import org.wordpress.mediapicker.MediaItem;
import org.wordpress.mediapicker.MediaPickerFragment;
import org.wordpress.mediapicker.source.MediaSource;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Allows users to select a variety of videos and images from any source.
*
* Title can be set either by defining a string resource, R.string.media_picker_title, or passing
* a String extra in the {@link android.content.Intent} with the key ACTIVITY_TITLE_KEY.
*
* Accepts Image and Video sources as arguments and displays each in a tab.
* - Use DEVICE_IMAGE_MEDIA_SOURCES_KEY with a {@link java.util.List} of {@link org.wordpress.mediapicker.source.MediaSource}'s to pass image sources via the Intent
* - Use DEVICE_VIDEO_MEDIA_SOURCES_KEY with a {@link java.util.List} of {@link org.wordpress.mediapicker.source.MediaSource}'s to pass video sources via the Intent
*/
public class MediaPickerActivity extends AppCompatActivity
implements MediaPickerFragment.OnMediaSelected {
/**
* Request code for the {@link android.content.Intent} to start media selection.
*/
public static final int ACTIVITY_REQUEST_CODE_MEDIA_SELECTION = 6000;
/**
* Result code signaling that media has been selected.
*/
public static final int ACTIVITY_RESULT_CODE_MEDIA_SELECTED = 6001;
/**
* Result code signaling that a gallery should be created with the results.
*/
public static final int ACTIVITY_RESULT_CODE_GALLERY_CREATED = 6002;
/**
* Pass a {@link String} with this key in the {@link android.content.Intent} to set the title.
*/
public static final String ACTIVITY_TITLE_KEY = "activity-title";
/**
* Pass an {@link java.util.ArrayList} of {@link org.wordpress.mediapicker.source.MediaSource}'s
* in the {@link android.content.Intent} to set image sources for selection.
*/
public static final String DEVICE_IMAGE_MEDIA_SOURCES_KEY = "device-image-media-sources";
/**
* Pass an {@link java.util.ArrayList} of {@link org.wordpress.mediapicker.source.MediaSource}'s
* in the {@link android.content.Intent} to set video sources for selection.
*/
public static final String DEVICE_VIDEO_MEDIA_SOURCES_KEY = "device- video=media-sources";
public static final String BLOG_IMAGE_MEDIA_SOURCES_KEY = "blog-image-media-sources";
public static final String BLOG_VIDEO_MEDIA_SOURCES_KEY = "blog-video-media-sources";
/**
* Key to extract the {@link java.util.ArrayList} of {@link org.wordpress.mediapicker.MediaItem}'s
* that were selected by the user.
*/
public static final String SELECTED_CONTENT_RESULTS_KEY = "selected-content";
private static final String CAPTURE_PATH_KEY = "capture-path";
private static final long TAB_ANIMATION_DURATION_MS = 250L;
private MediaPickerAdapter mMediaPickerAdapter;
private ArrayList<MediaSource>[] mMediaSources;
private TabLayout mTabLayout;
private WPViewPager mViewPager;
private ActionMode mActionMode;
private String mCapturePath;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lockRotation();
addMediaSources();
setTitle();
initializeContentView();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.media_picker, menu);
return true;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(CAPTURE_PATH_KEY, mCapturePath);
}
@Override
public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState.containsKey(CAPTURE_PATH_KEY)) {
mCapturePath = savedInstanceState.getString(CAPTURE_PATH_KEY);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
} else if (item.getItemId() == R.id.capture_image) {
WordPressMediaUtils.launchCamera(this, BuildConfig.APPLICATION_ID,
new WordPressMediaUtils.LaunchCameraCallback() {
@Override
public void onMediaCapturePathReady(String mediaCapturePath) {
mCapturePath = mediaCapturePath;
}
});
return true;
} else if (item.getItemId() == R.id.capture_video) {
WordPressMediaUtils.launchVideoCamera(this);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RequestCodes.TAKE_PHOTO:
File file = new File(mCapturePath);
Uri imageUri = Uri.fromFile(file);
if (file.exists() && MediaUtils.isValidImage(imageUri.toString())) {
// Notify MediaStore of new content
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, imageUri));
MediaItem newImage = new MediaItem();
newImage.setSource(imageUri);
newImage.setPreviewSource(imageUri);
ArrayList<MediaItem> imageResult = new ArrayList<>();
imageResult.add(newImage);
finishWithResults(imageResult, ACTIVITY_RESULT_CODE_MEDIA_SELECTED);
}
break;
case RequestCodes.TAKE_VIDEO:
Uri videoUri = data != null ? data.getData() : null;
if (videoUri != null) {
// Notify MediaStore of new content
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, videoUri));
MediaItem newVideo = new MediaItem();
newVideo.setSource(videoUri);
newVideo.setPreviewSource(videoUri);
ArrayList<MediaItem> videoResult = new ArrayList<>();
videoResult.add(newVideo);
finishWithResults(videoResult, ACTIVITY_RESULT_CODE_MEDIA_SELECTED);
}
break;
default:
break;
}
}
@Override
public void onBackPressed() {
if (mActionMode != null) {
mActionMode.finish();
} else {
finishWithResults(null, ACTIVITY_RESULT_CODE_MEDIA_SELECTED);
super.onBackPressed();
}
}
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
mViewPager.setPagingEnabled(false);
mActionMode = mode;
animateTabGone();
}
@Override
public void onActionModeFinished(ActionMode mode) {
super.onActionModeFinished(mode);
mViewPager.setPagingEnabled(true);
mActionMode = null;
animateTabAppear();
}
/*
OnMediaSelected interface
*/
@Override
public void onMediaSelectionStarted() {
}
@Override
public void onMediaSelected(MediaItem mediaContent, boolean selected) {
}
@Override
public void onMediaSelectionConfirmed(ArrayList<MediaItem> mediaContent) {
if (mediaContent != null) {
finishWithResults(mediaContent, ACTIVITY_RESULT_CODE_MEDIA_SELECTED);
} else {
finish();
}
}
@Override
public void onMediaSelectionCancelled() {
}
@Override
public boolean onMenuItemSelected(MenuItem menuItem, ArrayList<MediaItem> selectedContent) {
if (menuItem.getItemId() == R.id.menu_media_content_selection_gallery) {
finishWithResults(selectedContent, ACTIVITY_RESULT_CODE_GALLERY_CREATED);
}
return false;
}
@Override
public ImageLoader.ImageCache getImageCache() {
return WordPress.getBitmapCache();
}
/**
* Finishes the activity after the user has confirmed media selection.
*
* @param results
* list of selected media items
*/
private void finishWithResults(ArrayList<MediaItem> results, int resultCode) {
Intent result = new Intent();
result.putParcelableArrayListExtra(SELECTED_CONTENT_RESULTS_KEY, results);
setResult(resultCode, result);
finish();
}
/**
* Helper method; sets title to R.string.media_picker_title unless intent defines one
*/
private void setTitle() {
final Intent intent = getIntent();
if (intent != null && intent.hasExtra(ACTIVITY_TITLE_KEY)) {
String activityTitle = intent.getStringExtra(ACTIVITY_TITLE_KEY);
setTitle(activityTitle);
} else {
setTitle(getString(R.string.media_picker_title));
}
}
/**
* Helper method; gathers {@link org.wordpress.mediapicker.source.MediaSource}'s from intent
*/
private void addMediaSources() {
final Intent intent = getIntent();
if (intent != null) {
mMediaSources = new ArrayList[4];
List<MediaSource> mediaSources = intent.getParcelableArrayListExtra(DEVICE_IMAGE_MEDIA_SOURCES_KEY);
if (mediaSources != null) {
mMediaSources[0] = new ArrayList<>();
mMediaSources[0].addAll(mediaSources);
}
mediaSources = intent.getParcelableArrayListExtra(DEVICE_VIDEO_MEDIA_SOURCES_KEY);
if (mediaSources != null) {
mMediaSources[1] = new ArrayList<>();
mMediaSources[1].addAll(mediaSources);
}
mediaSources = intent.getParcelableArrayListExtra(BLOG_IMAGE_MEDIA_SOURCES_KEY);
if (mediaSources != null) {
mMediaSources[2] = new ArrayList<>();
mMediaSources[2].addAll(mediaSources);
}
mediaSources = intent.getParcelableArrayListExtra(BLOG_VIDEO_MEDIA_SOURCES_KEY);
if (mediaSources != null) {
mMediaSources[3] = new ArrayList<>();
mMediaSources[3].addAll(mediaSources);
}
}
}
/**
* Helper method; locks device orientation to its current state while media is being selected
*/
private void lockRotation() {
switch (getWindowManager().getDefaultDisplay().getRotation()) {
case Surface.ROTATION_0:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Surface.ROTATION_90:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_180:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_270:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
}
}
/**
* Helper method; sets up the tab bar, media adapter, and ViewPager for displaying media content
*/
private void initializeContentView() {
setContentView(R.layout.media_picker_activity);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.show();
}
mMediaPickerAdapter = new MediaPickerAdapter(getFragmentManager());
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
mViewPager = (WPViewPager) findViewById(R.id.media_picker_pager);
if (mViewPager != null) {
mViewPager.setPagingEnabled(true);
mMediaPickerAdapter.addTab(mMediaSources[0] != null ? mMediaSources[0] :
new ArrayList<MediaSource>(),
getString(R.string.tab_title_device_images),
getString(R.string.loading_images),
getString(R.string.error_loading_images),
getString(R.string.no_device_images));
mMediaPickerAdapter.addTab(mMediaSources[1] != null ? mMediaSources[1] :
new ArrayList<MediaSource>(),
getString(R.string.tab_title_device_videos),
getString(R.string.loading_videos),
getString(R.string.error_loading_videos),
getString(R.string.no_device_videos));
mMediaPickerAdapter.addTab(mMediaSources[2] != null ? mMediaSources[2] :
new ArrayList<MediaSource>(),
getString(R.string.tab_title_site_images),
getString(R.string.loading_blog_images),
getString(R.string.error_loading_blog_images),
getString(R.string.no_blog_images));
mMediaPickerAdapter.addTab(mMediaSources[3] != null ? mMediaSources[3] :
new ArrayList<MediaSource>(),
getString(R.string.tab_title_site_videos),
getString(R.string.loading_blog_videos),
getString(R.string.error_loading_blog_videos),
getString(R.string.no_blog_videos));
mViewPager.setAdapter(mMediaPickerAdapter);
if (mTabLayout != null) {
int normalColor = getResources().getColor(R.color.blue_light);
int selectedColor = getResources().getColor(R.color.white);
mTabLayout.setTabTextColors(normalColor, selectedColor);
mTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
mTabLayout.setupWithViewPager(mViewPager);
}
}
}
/**
* Helper method; animates the tab bar and ViewPager in when ActionMode ends
*/
private void animateTabAppear() {
TranslateAnimation tabAppearAnimation = new TranslateAnimation(0, 0, -mTabLayout.getHeight(), 0);
TranslateAnimation pagerAppearAnimation = new TranslateAnimation(0, 0, -mTabLayout.getHeight(), 0);
tabAppearAnimation.setDuration(TAB_ANIMATION_DURATION_MS);
pagerAppearAnimation.setDuration(TAB_ANIMATION_DURATION_MS);
pagerAppearAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mViewPager.getWidth(), mViewPager.getHeight() - mTabLayout.getHeight());
mViewPager.setLayoutParams(params);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mTabLayout.setVisibility(View.VISIBLE);
mViewPager.startAnimation(pagerAppearAnimation);
mTabLayout.startAnimation(tabAppearAnimation);
}
/**
* Helper method; animates the tab bar and ViewPager out when ActionMode begins
*/
private void animateTabGone() {
TranslateAnimation tabGoneAnimation = new TranslateAnimation(0, 0, 0, -mTabLayout.getHeight());
TranslateAnimation pagerGoneAnimation = new TranslateAnimation(0, 0, 0, -mTabLayout.getHeight());
tabGoneAnimation.setDuration(TAB_ANIMATION_DURATION_MS);
pagerGoneAnimation.setDuration(TAB_ANIMATION_DURATION_MS);
tabGoneAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
mTabLayout.setVisibility(View.GONE);
mTabLayout.clearAnimation();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
pagerGoneAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
LinearLayout.LayoutParams newParams = new LinearLayout.LayoutParams(mViewPager.getWidth(), mViewPager.getHeight() + mTabLayout.getHeight());
mViewPager.setLayoutParams(newParams);
}
@Override
public void onAnimationEnd(Animation animation) {
mViewPager.clearAnimation();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mTabLayout.startAnimation(tabGoneAnimation);
mViewPager.startAnimation(pagerGoneAnimation);
}
/**
* Shows {@link org.wordpress.mediapicker.MediaPickerFragment}'s in a tabbed layout.
*/
public class MediaPickerAdapter extends FragmentPagerAdapter {
private class MediaPicker {
public String loadingText;
public String errorText;
public String emptyText;
public String pickerTitle;
public ArrayList<MediaSource> mediaSources;
public MediaPicker(String name, String loading, String error, String empty, ArrayList<MediaSource> sources) {
loadingText = loading;
errorText = error;
emptyText = empty;
pickerTitle = name;
mediaSources = sources;
}
}
private final List<MediaPicker> mMediaPickers;
private MediaPickerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
mMediaPickers = new ArrayList<>();
}
@Override
public Fragment getItem(int position) {
if (position < mMediaPickers.size()) {
MediaPicker mediaPicker = mMediaPickers.get(position);
MediaPickerFragment fragment = new MediaPickerFragment();
fragment.setLoadingText(mediaPicker.loadingText);
fragment.setErrorText(mediaPicker.errorText);
fragment.setEmptyText(mediaPicker.emptyText);
fragment.setActionModeMenu(R.menu.menu_media_picker_action_mode);
fragment.setMediaSources(mediaPicker.mediaSources);
return fragment;
}
return null;
}
@Override
public int getCount() {
return mMediaPickers.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mMediaPickers.get(position).pickerTitle;
}
public void addTab(ArrayList<MediaSource> mediaSources, String tabName, String loading, String error, String empty) {
mMediaPickers.add(new MediaPicker(tabName, loading, error, empty, mediaSources));
}
}
}