com.lcl6.cn.imagepickerl.AndroidImagePicker.java Source code

Java tutorial

Introduction

Here is the source code for com.lcl6.cn.imagepickerl.AndroidImagePicker.java

Source

/*
 *
 *  * Copyright (C) 2015 Eason.Lai (easonline7@gmail.com)
 *  *
 *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  * you may not use this file except in compliance with the License.
 *  * You may obtain a copy of the License at
 *  *
 *  *      http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 *
 */

package com.lcl6.cn.imagepickerl;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.util.Log;

import com.lcl6.cn.imagepickerl.bean.ImageItem;
import com.lcl6.cn.imagepickerl.bean.ImageSet;
import com.lcl6.cn.imagepickerl.ui.ImagesGridActivity;
import com.lcl6.cn.imagepickerl.utils.Util;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/**
 * <b>The main Entrance of this lib</b><br/>
 * Created by Eason.Lai on 2015/11/1 10:42 <br/>
 * contacteasonline7@gmail.com <br/>
 */
public class AndroidImagePicker {
    public static final String TAG = AndroidImagePicker.class.getSimpleName();

    public static final int REQ_CAMERA = 1431;
    public static final int REQ_PREVIEW = 2347;

    public static final String KEY_PIC_PATH = "key_pic_path";
    public static final String KEY_PIC_SELECTED_POSITION = "key_pic_selected";

    public boolean cropMode = false;
    public int cropSize = 60 * 2;

    private static AndroidImagePicker mInstance;

    public static AndroidImagePicker getInstance() {
        if (mInstance == null) {
            synchronized (AndroidImagePicker.class) {
                if (mInstance == null) {
                    mInstance = new AndroidImagePicker();
                }
            }
        }
        return mInstance;
    }

    /**
     * ?
     */
    private int selectLimit = 3;//can select 9 at most,you can change it yourself

    public int getSelectLimit() {
        return selectLimit;
    }

    public void setSelectLimit(int selectLimit) {
        this.selectLimit = selectLimit;
    }

    /**
     * ?
     */
    private int selectMode = Select_Mode.MODE_MULTI;//Select mode:single or multi

    public int getSelectMode() {
        return selectMode;
    }

    private void setSelectMode(int selectMode) {
        this.selectMode = selectMode;
    }

    /**
     * ?
     */
    private boolean shouldShowCamera = true;//indicate whether to show the camera item

    public boolean isShouldShowCamera() {
        return shouldShowCamera;
    }

    private void setShouldShowCamera(boolean shouldShowCamera) {
        this.shouldShowCamera = shouldShowCamera;
    }

    /**
     * ??
     */
    private String mCurrentPhotoPath;//image saving path when taking pictures

    public String getCurrentPhotoPath() {
        return mCurrentPhotoPath;
    }

    /**
     * Listeners of image selected changes,if you want to custom the Activity of ImagesGrid or ImagePreview,you might use it.
     */
    private List<OnImageSelectedChangeListener> mImageSelectedChangeListeners;

    public void addOnImageSelectedChangeListener(OnImageSelectedChangeListener l) {
        if (mImageSelectedChangeListeners == null) {
            mImageSelectedChangeListeners = new ArrayList<>();
            Log.i(TAG, "=====create new ImageSelectedListener List");
        }
        this.mImageSelectedChangeListeners.add(l);
        Log.i(TAG, "=====addOnImageSelectedChangeListener:" + l.getClass().toString());
    }

    public void removeOnImageItemSelectedChangeListener(OnImageSelectedChangeListener l) {
        if (mImageSelectedChangeListeners == null) {
            return;
        }
        Log.i(TAG, "=====remove from mImageSelectedChangeListeners:" + l.getClass().toString());
        this.mImageSelectedChangeListeners.remove(l);
    }

    private void notifyImageSelectedChanged(int position, ImageItem item, boolean isAdd) {
        if ((isAdd && getSelectImageCount() > selectLimit) || (!isAdd && getSelectImageCount() == selectLimit)) {
            //do not call the listeners if reached the select limit when selecting
            Log.i(TAG, "=====ignore notifyImageSelectedChanged:isAdd?" + isAdd);
        } else {
            if (mImageSelectedChangeListeners == null) {
                return;
            }
            Log.i(TAG, "=====notify mImageSelectedChangeListeners:item=" + item.path);
            for (OnImageSelectedChangeListener l : mImageSelectedChangeListeners) {
                l.onImageSelectChange(position, item, mSelectedImages.size(), selectLimit);
            }
        }
    }

    /**
     * listeners of image crop complete
     * ??
     */
    private List<OnImageCropCompleteListener> mImageCropCompleteListeners;

    public void addOnImageCropCompleteListener(OnImageCropCompleteListener l) {
        if (mImageCropCompleteListeners == null) {
            mImageCropCompleteListeners = new ArrayList<>();
            Log.i(TAG, "=====create new ImageCropCompleteListener List");
        }
        this.mImageCropCompleteListeners.add(l);
        Log.i(TAG, "=====addOnImageCropCompleteListener:" + l.getClass().toString());
    }

    public void removeOnImageCropCompleteListener(OnImageCropCompleteListener l) {
        if (mImageCropCompleteListeners == null) {
            return;
        }
        this.mImageCropCompleteListeners.remove(l);
        Log.i(TAG, "=====remove mImageCropCompleteListeners:" + l.getClass().toString());
    }

    public void notifyImageCropComplete(Bitmap bmp, int ratio) {
        if (mImageCropCompleteListeners != null) {
            Log.i(TAG, "=====notify onImageCropCompleteListener  bitmap=" + bmp.toString() + "  ratio=" + ratio);
            for (OnImageCropCompleteListener l : mImageCropCompleteListeners) {
                l.onImageCropComplete(bmp, ratio);
            }
        }
    }

    /**
     * Listener when image pick completed
     * ?
     */
    private OnImagePickCompleteListener mOnImagePickCompleteListener;

    public void setOnImagePickCompleteListener(OnImagePickCompleteListener l) {
        this.mOnImagePickCompleteListener = l;
        Log.i(TAG, "=====setOnImagePickCompleteListener:" + l.getClass().toString());
    }

    public void deleteOnImagePickCompleteListener(OnImagePickCompleteListener l) {
        if (l.getClass().getName().equals(mOnImagePickCompleteListener.getClass().getName())) {
            mOnImagePickCompleteListener = null;
            Log.i(TAG, "=====remove mOnImagePickCompleteListener:" + l.getClass().toString());
            System.gc();
        }
    }

    public void notifyOnImagePickComplete() {
        if (mOnImagePickCompleteListener != null) {
            List<ImageItem> list = getSelectedImages();
            Log.i(TAG, "=====notify mOnImagePickCompleteListener:selected size=" + list.size());
            mOnImagePickCompleteListener.onImagePickComplete(list);
        }
    }

    //All Images collect by Set
    private List<ImageSet> mImageSets;
    private int mCurrentSelectedImageSetPosition = 0;//Item 0: all images

    Set<ImageItem> mSelectedImages = new LinkedHashSet<>();

    public List<ImageSet> getImageSets() {
        return mImageSets;
    }

    public List<ImageItem> getImageItemsOfCurrentImageSet() {
        if (mImageSets != null) {
            return mImageSets.get(mCurrentSelectedImageSetPosition).imageItems;
        } else {
            return null;
        }
    }

    public void setImageSets(List<ImageSet> mImageSets) {
        this.mImageSets = mImageSets;
    }

    public void clearImageSets() {
        if (mImageSets != null) {
            mImageSets.clear();
            mImageSets = null;
        }
    }

    public int getCurrentSelectedImageSetPosition() {
        return mCurrentSelectedImageSetPosition;
    }

    public void setCurrentSelectedImageSetPosition(int mCurrentSelectedImageSetPosition) {
        this.mCurrentSelectedImageSetPosition = mCurrentSelectedImageSetPosition;
    }

    public void addSelectedImageItem(int position, ImageItem item) {
        mSelectedImages.add(item);
        Log.i(TAG, "=====addSelectedImageItem:" + item.path);
        notifyImageSelectedChanged(position, item, true);
    }

    public void deleteSelectedImageItem(int position, ImageItem item) {
        mSelectedImages.remove(item);
        Log.i(TAG, "=====deleteSelectedImageItem:" + item.path);
        notifyImageSelectedChanged(position, item, false);
    }

    public boolean isSelect(int position, ImageItem item) {
        return mSelectedImages.contains(item);
    }

    public int getSelectImageCount() {
        if (mSelectedImages == null) {
            return 0;
        }
        return mSelectedImages.size();
    }

    public void onDestroy() {
        if (mImageSelectedChangeListeners != null) {
            mImageSelectedChangeListeners.clear();
            mImageSelectedChangeListeners = null;
        }
        if (mImageCropCompleteListeners != null) {
            mImageCropCompleteListeners.clear();
            mImageCropCompleteListeners = null;
        }

        //mSelectedImages.clear();
        //mSelectedImages = null;

        clearImageSets();

        mCurrentSelectedImageSetPosition = 0;

        Log.i(TAG, "=====destroy:clear all data and listeners");
    }

    public List<ImageItem> getSelectedImages() {
        List<ImageItem> list = new ArrayList<>();
        list.addAll(mSelectedImages);
        return list;
    }

    public void clearSelectedImages() {
        if (mSelectedImages != null) {
            mSelectedImages.clear();
            Log.i(TAG, "=====clear all selected images");
        }
    }

    public static Bitmap makeCropBitmap(Bitmap bitmap, Rect rectBox, RectF imageMatrixRect, int expectSize) {
        Bitmap bmp = bitmap;
        RectF localRectF = imageMatrixRect;
        float f = localRectF.width() / bmp.getWidth();
        int left = (int) ((rectBox.left - localRectF.left) / f);
        int top = (int) ((rectBox.top - localRectF.top) / f);
        int width = (int) (rectBox.width() / f);
        int height = (int) (rectBox.height() / f);

        if (left < 0) {
            left = 0;
        }
        if (top < 0) {
            top = 0;
        }

        if (left + width > bmp.getWidth()) {
            width = bmp.getWidth() - left;
        }
        if (top + height > bmp.getHeight()) {
            height = bmp.getHeight() - top;
        }

        int k = width;
        if (width < expectSize) {
            k = expectSize;
        }
        if (width > expectSize) {
            k = expectSize;
        }

        try {
            bmp = Bitmap.createBitmap(bmp, left, top, width, height);

            if (k != width && k != height) {//don't do this if equals
                bmp = Bitmap.createScaledBitmap(bmp, k, k, true);//scale the bitmap
            }

        } catch (OutOfMemoryError localOutOfMemoryError1) {
            Log.v(TAG, "OOM when create bitmap");
        }
        return bmp;
    }

    /**
     * create a file to save photo
     * @param ctx
     * @return
     */
    private File createImageSaveFile(Context ctx) {
        if (Util.isStorageEnable()) {
            // 
            File pic = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            if (!pic.exists()) {
                pic.mkdirs();
            }
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
            String fileName = "IMG_" + timeStamp;
            File tmpFile = new File(pic, fileName + ".jpg");
            mCurrentPhotoPath = tmpFile.getAbsolutePath();
            Log.i(TAG, "=====camera path:" + mCurrentPhotoPath);
            return tmpFile;
        } else {
            //File cacheDir = ctx.getCacheDir();
            File cacheDir = Environment.getDataDirectory();
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
            String fileName = "IMG_" + timeStamp;
            File tmpFile = new File(cacheDir, fileName + ".jpg");
            mCurrentPhotoPath = tmpFile.getAbsolutePath();
            Log.i(TAG, "=====camera path:" + mCurrentPhotoPath);
            return tmpFile;
        }

    }

    /**
     * take picture
     */
    public void takePicture(Activity act, int requestCode) throws IOException {

        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(act.getPackageManager()) != null) {
            // Create the File where the photo should go
            //File photoFile = createImageFile();
            File photoFile = createImageSaveFile(act);
            // Continue only if the File was successfully created
            if (photoFile != null) {
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
            }
        }
        act.startActivityForResult(takePictureIntent, requestCode);

    }

    /**
     * take picture
     */
    public void takePicture(Fragment fragment, int requestCode) throws IOException {

        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //Intent takePictureIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
        takePictureIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(fragment.getContext().getPackageManager()) != null) {
            // Create the File where the photo should go
            //File photoFile = createImageFile();
            File photoFile = createImageSaveFile(fragment.getContext());
            // Continue only if the File was successfully created
            if (photoFile != null) {
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                Log.i(TAG, "=====file ready to take photo:" + photoFile.getAbsolutePath());
            }
        }
        fragment.startActivityForResult(takePictureIntent, requestCode);

    }

    /**
     * scan the photo so that the gallery can read it
     * @param ctx
     * @param path
     */
    public static void galleryAddPic(Context ctx, String path) {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File(path);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        ctx.sendBroadcast(mediaScanIntent);
        Log.i(TAG, "=====MediaScan:" + path);
    }

    /**
     * listener for one Image Item selected observe
     */
    public interface OnImageSelectedChangeListener {
        void onImageSelectChange(int position, ImageItem item, int selectedItemsCount, int maxSelectLimit);
    }

    public interface OnImageCropCompleteListener {
        void onImageCropComplete(Bitmap bmp, float ratio);
    }

    public interface OnImagePickCompleteListener {
        void onImagePickComplete(List<ImageItem> items);
    }

    public interface Select_Mode {
        int MODE_SINGLE = 0;
        int MODE_MULTI = 1;
    }

    /**
     * ?
     * @param act Activity
     * @param showCamera ???
     * @param l Listener
     */
    public void pickSingle(Activity act, boolean showCamera, OnImagePickCompleteListener l) {
        //
        setSelectMode(Select_Mode.MODE_SINGLE);
        setShouldShowCamera(showCamera);
        setOnImagePickCompleteListener(l);
        cropMode = false;
        act.startActivity(new Intent(act, ImagesGridActivity.class));
    }

    /**
     * 
     * @param act Activity
     * @param showCamera ???
     * @param l Listener
     */
    public void pickMulti(Activity act, boolean showCamera, OnImagePickCompleteListener l) {
        //
        setSelectMode(Select_Mode.MODE_MULTI);
        setShouldShowCamera(showCamera);
        setOnImagePickCompleteListener(l);
        cropMode = false;
        act.startActivity(new Intent(act, ImagesGridActivity.class));
    }

    /**
     * ???
     * @param act
     * @param showCamera
     * @param cropSize
     * @param l
     */
    public void pickAndCrop(Activity act, boolean showCamera, int cropSize, OnImageCropCompleteListener l) {
        setSelectMode(Select_Mode.MODE_SINGLE);
        setShouldShowCamera(showCamera);
        addOnImageCropCompleteListener(l);
        cropMode = true;
        this.cropSize = cropSize;

        act.startActivity(new Intent(act, ImagesGridActivity.class));
    }

}