| 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)); |
| } |
| } |
| } |