zoukankan      html  css  js  c++  java
  • 封装了一个类,让你用几代码就能获得相册或拍照得到的图片

    一、最终成果

      

    本例是用android自带的相册获取图片的,并且处理了很多异常,最终你的activity只需要用很少的代码就能获得用户选择好的图片了。

    例子:

       <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

    加完权限后就可以编码啦~

    package com.example.jack.getphoto;
    
    import com.kale.lib.activity.KaleBaseActivity;
    import com.kale.lib.photo.GetSimplePhotoHelper;
    import com.kale.lib.photo.SimplePhoto;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    /**
     * @author Jack Tony
     *         <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     *         <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
     * @date 2015/4/26
     */
    public class MainActivity extends KaleBaseActivity implements View.OnClickListener {
    
        private ImageView photoImageView;
    
        private Button fromAlbumButton;
    
        private Button fromCameraButton;
    
        GetSimplePhotoHelper mPhotoHelper;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mPhotoHelper = GetSimplePhotoHelper.getInstance(this);
        }
    
        protected void findViews() {
            photoImageView = getView(R.id.photo_imageView);
            fromAlbumButton = getView(R.id.fromAlbum_button);
            fromCameraButton = getView(R.id.fromCamera_button);
            photoImageView = getView(R.id.photo_imageView);
        }
    
        @Override
        protected void beforeSetViews() {
            
        }
    
        @Override
        protected void setViews() {
            fromAlbumButton.setOnClickListener(this);
            fromCameraButton.setOnClickListener(this);
        }
    
        @Override
        protected int getContentViewId() {
            return R.layout.activity_main;
        }
    
        @Override
        public void onClick(View v) {
            if (v == fromAlbumButton) {
                // Handle clicks for fromAlbumButton
                // 去选择图片,photo的路径设置为null就好
                mPhotoHelper.choicePhoto(GetSimplePhotoHelper.FROM_ALBUM, null,new MyListener());
            } else if (v == fromCameraButton) {
                // Handle clicks for fromCameraButton
                mPhotoHelper.choicePhoto(GetSimplePhotoHelper.FROM_CAMERA, null,new MyListener());
                // 可以设置拍照后图片图片保存的自定义路径,如果不设置路径,那么拍照后的照片不会保存在sd卡中
                //mPhotoHelper.choicePhoto(GetSimplePhotoHelper.FROM_WAY.FROM_CAMERA, Environment.getExternalStorageDirectory()+ "/my_temp.jpg");
            }
        }
        
        class MyListener implements GetSimplePhotoHelper.OnSelectedPhotoListener {
    
    
            @Override
            public void onSelectedPhoto(int fromWay, SimplePhoto photo) {
                if (photo != null) {
                    photoImageView.setImageBitmap(photo.bitmap);
                    Log.d(TAG, "uri = " + photo.uri.toString());
                    Log.d(TAG, "photo's degree = " + photo.degree);
                }
            }
        }
    
        
    }

    很简单吧,那么下面我们来看看如何实现这个功能。

    二、GetSimplePhotoHelper

    package com.kale.lib.photo;
    
    
    import com.kale.lib.utils.BitmapUtil;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.support.annotation.IntDef;
    
    import java.io.File;
    
    /**
     * @author Jack Tony
     *         从相册或者从照相机得到一个图片,没有裁剪功能
     * @date 2015/4/24
     */
    public class GetSimplePhotoHelper {
    
        public static final int FROM_ALBUM = 0;
    
        public static final int FROM_CAMERA = 1;
    
        @IntDef({GetSimplePhotoHelper.FROM_ALBUM, GetSimplePhotoHelper.FROM_CAMERA})
        private @interface from {
    
        }
    
        private Activity mActivity;
    
        private String mPicFilePath;
    
        private int mFromWay;
    
        private GetSimplePhotoHelper(Activity activity) {
            mActivity = activity;
        }
    
        private static GetSimplePhotoHelper instance;
    
        public static GetSimplePhotoHelper getInstance(Activity activity) {
            if (instance == null) {
                instance = new GetSimplePhotoHelper(activity);
            }
            return instance;
        }
    
        /**
         * 从相册或照相机获得一张图片
         *
         * @param way         获取图片的途径
         * @param picFilePath 如果需要保存从相机拍摄的图片,请指定保存图片的全部路径(通过相机拍照时才有效)
         *                    eg:GetPhotoHelper.choicePhoto(GetPhotoHelper.FROM_WAY.FROM_CAMERA, Environment.getExternalStorageDirectory()+ "/temp.jpg");
         */
        public void choicePhoto(@from final int way, String picFilePath, OnSelectedPhotoListener listener) {
            mFromWay = way;
            mPicFilePath = picFilePath;
            if (way == FROM_ALBUM) {
                choicePhotoFromAlbum();
            } else if (way == FROM_CAMERA) {
                choicePhotoFromCamera(picFilePath);
            }
            mListener = listener;
        }
    
        /**
         * 启动相册的activity
         */
        private void choicePhotoFromAlbum() {
            Intent intent = new Intent(mActivity, GetSimplePhotoActivity.class);
            intent.putExtra(GetSimplePhotoActivity.KEY_FROM_WAY, GetSimplePhotoActivity.VALUE_FROM_ALBUM);
            mActivity.startActivityForResult(intent, 0);
        }
    
        /**
         * 启动相机的activity
         */
        private void choicePhotoFromCamera(String picFilePath) {
            Intent intent = new Intent(mActivity, GetSimplePhotoActivity.class);
            intent.putExtra(GetSimplePhotoActivity.KEY_FROM_WAY, GetSimplePhotoActivity.VALUE_FROM_CAMERA);
            intent.putExtra(GetSimplePhotoActivity.KEY_PHOTO_PATH, picFilePath);
            mActivity.startActivityForResult(intent, 0);
        }
    
    
        /**
         * 得到已经选择好的图片,这个方法必须在onActivityResult中进行回调
         *
         * @return 已经选择好的bitmap
         */
        protected void getSelectedPhoto(Uri uri) {
            //Logger.d("uri = " + uri);
            Bitmap bitmap = BitmapFactory.decodeFile(uri.toString());
            // Logger.d("方向 =" + GetSimplePhotoUtil.getOrientation(uri));
            if (bitmap != null) {
                bitmap = BitmapUtil.rotateBitmap(bitmap, GetSimplePhotoUtil.getPhotoDegreeByUri(uri));
            }
            SimplePhoto photo = new SimplePhoto();
            photo.bitmap = bitmap;
            photo.uri = uri;
            photo.degree = GetSimplePhotoUtil.getPhotoDegreeByUri(uri);
    
            // 如果来源是相机,而且没有指定图片保存的目录,那么使用完毕后就立刻删除相片
            if (mFromWay == FROM_CAMERA && mPicFilePath == null) {
                File tempPicFile = new File(uri.toString());
                if (tempPicFile != null) {
                    tempPicFile.delete();//设置成功后清除之前的照片文件
                }
            }
            mListener.onSelectedPhoto(mFromWay,photo);
        }
    
        private OnSelectedPhotoListener mListener;
    
        public interface OnSelectedPhotoListener {
    
            public void onSelectedPhoto(int way,SimplePhoto photo);
    
        }
    
    }

    这个类主要是获得activity并且获得用户期望获取图片的途径,并且告诉GetSimplePhotoActivity(真正的处理类)。如果是想通过相机获取图片,那么这里还可以指定拍摄的照片保存的路径,不设置就不保存照片。最后,它还处理了照片返回的结果,判断照片的方向,进行正确的旋转产生最终的bitmap。总之,这个类做的是获得用户获取图片的途径,之后启动activity来进行处理。在处理结束后,它进行结果的解析,最终返回一个SimplePhoto对象。

    三、GetSimplePhotoActivity

    GetSimplePhotoActivity是真正的处理类,用来启动系统相册或者是系统相机来获取图片。在启动系统相册的时候需要有个版本判断,在高版本上获得的uri可能会有点问题,所以这里需要判断不同的版本,进行不同的处理。同时,它还应该对于获得的图片进行回调,返回一个uri。

    package com.kale.lib.photo;
    
    
    import com.kale.lib.utils.IntentUtil;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Environment;
    
    import java.io.File;
    
    /**
     * @author Jack Tony
     * @date 2015/4/24
     */
    public class GetSimplePhotoActivity extends Activity {
    
        private class RequestCode {
    
            public static final int ALBUM_OK = 1, ALBUM_OK_KITKAT = 2, CAMERA_OK = 3;
        }
    
        /**
         * 准备通过什么样的方式来获取图片
         */
        public static final String KEY_FROM_WAY = "key_from_way";
    
        /**
         * 图片的全部路径
         */
        public static final String KEY_PHOTO_PATH = "key_photo_path";
    
    
        public static final int VALUE_FROM_ALBUM = 54345;
    
        public static final int VALUE_FROM_CAMERA = 46632;
    
        public static final String TEMP_PHOTO_FILE_NAME = "kale_temp_photo.jpg";
    
        private File tempPicFile;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            if (!IntentUtil.isBundleEmpty(getIntent())) {
                Bundle bundle = getIntent().getExtras();
                if (bundle.getInt(KEY_FROM_WAY, VALUE_FROM_ALBUM) == VALUE_FROM_ALBUM) {
                    // 进行版本判断 see:http://blog.csdn.net/tempersitu/article/details/20557383
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
                        GetSimplePhotoUtil.choicePicFromAlbum_kitkat(this, RequestCode.ALBUM_OK_KITKAT);
                    } else {
                        // 4.4以下
                        GetSimplePhotoUtil.choicePicFromAlbum(this, RequestCode.ALBUM_OK);
                    }
                } else {
                    if (bundle.getString(KEY_PHOTO_PATH) == null) {
                        // 照相得到的图片默认的保存路径,用完后会自动删除
                        tempPicFile = new File(Environment.getExternalStorageDirectory(), TEMP_PHOTO_FILE_NAME);
                    } else {
                        // 自定义照相得到的图片的保存路径,不会自动删除
                        tempPicFile = new File(bundle.getString(KEY_PHOTO_PATH));
                    }
                    tempPicFile.delete();// 清空之前的文件
                    GetSimplePhotoUtil.choicePicFromCamera(this, tempPicFile, RequestCode.CAMERA_OK);
                }
            }
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            Uri uri;
            switch (requestCode) {
                // 如果是直接从相册获取
                case RequestCode.ALBUM_OK:
                    //从相册中获取到图片
                    if (data != null) {
                        uri = data.getData();
                        finishAndReturnBitmap(uri);
                    } else {
                        finish();
                    }
                    break;
                case RequestCode.ALBUM_OK_KITKAT:
                    if (data != null) {
                        uri = Uri.parse(GetSimplePhotoUtil.getPath(this, data.getData()));
                        finishAndReturnBitmap(uri);
                    } else {
                        finish();
                    }
                    break;
                // 如果是调用相机拍照时
                case RequestCode.CAMERA_OK:
                    // 当拍照到照片时操作
                    if (tempPicFile.exists()) {
                        uri = Uri.parse(tempPicFile.getAbsolutePath());
                        finishAndReturnBitmap(uri);
                    } else {
                        finish();
                    }
                    break;
                default:
                    break;
            }
        }
    
        public void finishAndReturnBitmap(Uri uri) {
            GetSimplePhotoHelper.getInstance(this).getSelectedPhoto(uri);
            finish();
        }
    }

    四、工具类和模型类

    GetSimplePhotoUtil

    package com.kale.lib.photo;
    
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.content.ContentUris;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.media.ExifInterface;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Environment;
    import android.provider.DocumentsContract;
    import android.provider.MediaStore;
    
    import java.io.File;
    import java.io.IOException;
    
    /**
     * @author Jack Tony
     * @brief
     * @date 2015/4/25
     */
    class GetSimplePhotoUtil {
    
        /**
         * 从相册获取图片
         */
        public static void choicePicFromAlbum(Activity activity, int requestCode) {
            // 来自相册
            Intent albumIntent = new Intent(Intent.ACTION_GET_CONTENT);
            albumIntent.addCategory(Intent.CATEGORY_OPENABLE);
            albumIntent.setType("image/*");
            activity.startActivityForResult(albumIntent, requestCode);
        }
    
        /**
         * 4.4以上版本使用
         * @see "http://blog.csdn.net/tempersitu/article/details/20557383"
         * 
         * @param activity
         * @param requestCode
         */
        public static void choicePicFromAlbum_kitkat(Activity activity, int requestCode) {
            // 来自相册
            Intent albumIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            albumIntent.addCategory(Intent.CATEGORY_OPENABLE);
            albumIntent.setType("image/*");
            activity.startActivityForResult(albumIntent, requestCode);
        }
    
        /**
         * 拍照后获取图片
         *
         * @param activity           
         * @param cameraPhotoFile 照片的文件
         * @param requestCode
         */
        public static void choicePicFromCamera(Activity activity, File cameraPhotoFile,int requestCode) {
            // 来自相机
            Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            // 下面这句指定调用相机拍照后的照片存储的路径,这样通过这个uri就可以得到这个照片了
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraPhotoFile));
            activity.startActivityForResult(cameraIntent, requestCode);// CAMERA_OK是用作判断返回结果的标识
        }
    
        private int aspectX = 1000;
    
        private int aspectY = 1000;
    
        private int outputX = 1;
    
        private int outputY = 1;
    
        private boolean shouldBeClip = false;
    
        private boolean shouldBeScale = false;
    
        /**
         * 设置比率,比如1:1
         */
        public void setAspectX(int aspectX, int aspectY) {
            this.aspectX = aspectX;
            this.aspectY = aspectY;
        }
    
        /**
         * 设置裁剪出来的图片的宽高
         */
        public void setOutputX(int outputX, int outputY) {
            this.outputX = outputX;
            this.outputY = outputY;
        }
    
    
        /**
         * 裁剪时是否保留图片的比例,如果是true那么就是保留
         */
        public void setShouldBeScale(boolean shoubeScale) {
            this.shouldBeScale = shoubeScale;
        }
    
        /**
         * 4.4得到的uri,需要以下方法来获取文件的路径
         * 
         * @param context
         * @param uri
         * @return
         */
        @SuppressLint("NewApi")
        public static String getPath(final Context context, final Uri uri) {
    
            final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    
            // DocumentProvider  
            if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
                // ExternalStorageProvider  
                if (isExternalStorageDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
    
                    if ("primary".equalsIgnoreCase(type)) {
                        return Environment.getExternalStorageDirectory() + "/" + split[1];
                    }
    
                    // TODO handle non-primary volumes  
                }
                // DownloadsProvider  
                else if (isDownloadsDocument(uri)) {
    
                    final String id = DocumentsContract.getDocumentId(uri);
                    final Uri contentUri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
    
                    return getDataColumn(context, contentUri, null, null);
                }
                // MediaProvider  
                else if (isMediaDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
    
                    Uri contentUri = null;
                    if ("image".equals(type)) {
                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    } else if ("video".equals(type)) {
                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    } else if ("audio".equals(type)) {
                        contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    }
    
                    final String selection = "_id=?";
                    final String[] selectionArgs = new String[] {
                            split[1]
                    };
    
                    return getDataColumn(context, contentUri, selection, selectionArgs);
                }
            }
            // MediaStore (and general)  
            else if ("content".equalsIgnoreCase(uri.getScheme())) {
    
                // Return the remote address  
                if (isGooglePhotosUri(uri))
                    return uri.getLastPathSegment();
    
                return getDataColumn(context, uri, null, null);
            }
            // File  
            else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }
    
            return null;
        }
    
        /**
         * Get the value of the data column for this Uri. This is useful for 
         * MediaStore Uris, and other file-based ContentProviders. 
         *
         * @param context The context. 
         * @param uri The Uri to query. 
         * @param selection (Optional) Filter used in the query. 
         * @param selectionArgs (Optional) Selection arguments used in the query. 
         * @return The value of the _data column, which is typically a file path. 
         */
        private static String getDataColumn(Context context, Uri uri, String selection,
                String[] selectionArgs) {
    
            Cursor cursor = null;
            final String column = "_data";
            final String[] projection = {
                    column
            };
    
            try {
                cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                        null);
                if (cursor != null && cursor.moveToFirst()) {
                    final int index = cursor.getColumnIndexOrThrow(column);
                    return cursor.getString(index);
                }
            } finally {
                if (cursor != null)
                    cursor.close();
            }
            return null;
        }
    
    
        /**
         * @param uri The Uri to check. 
         * @return Whether the Uri authority is ExternalStorageProvider. 
         */
        private static boolean isExternalStorageDocument(Uri uri) {
            return "com.android.externalstorage.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri The Uri to check. 
         * @return Whether the Uri authority is DownloadsProvider. 
         */
        private static boolean isDownloadsDocument(Uri uri) {
            return "com.android.providers.downloads.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri The Uri to check. 
         * @return Whether the Uri authority is MediaProvider. 
         */
        private static boolean isMediaDocument(Uri uri) {
            return "com.android.providers.media.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri The Uri to check. 
         * @return Whether the Uri authority is Google Photos. 
         */
        private static boolean isGooglePhotosUri(Uri uri) {
            return "com.google.android.apps.photos.content".equals(uri.getAuthority());
        }
    
        /**
         * 得到图片的方向
         * 
         * @param photoUri    
         * @return
         */
        public static int getOrientation(final Uri photoUri) {
            ExifInterface exifInterface = null;
            try {
                exifInterface = new ExifInterface(photoUri.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
        }
    
        /**
         * 通过photo的uri来得到图片的角度,从而判断是否需要进行旋转操作
         *
         * @param uri
         * @return
         */
        public static int getPhotoDegreeByUri(Uri uri) {
            int degree = 0;
            int orientation = GetSimplePhotoUtil.getOrientation(uri);
            if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
                degree = 90;
            } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
                degree = 180;
            } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
                degree = 270;
            }
            return degree;
        }
    
    }

    SimplePhoto

    package com.kale.lib.photo;
    
    import android.graphics.Bitmap;
    import android.net.Uri;
    
    /**
     * @author Jack Tony
     * @brief
     * @date 2015/4/26
     */
    public class SimplePhoto {
    
        /**
         * 图片的uri,其实就是地址。eg:/storage/sdcard0/Tencent/QQ_Images/-1935240a504f548c.jpg
         */
        public Uri uri;
    
        /**
         * 图像需要旋转的角度。方向不正确的图像可以根据这个进行旋转操作
         */
        public int degree;
    
        /**
         * 图像的bitmap
         */
        public Bitmap bitmap;
    }

    五、配置文件

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.kale.lib">
    
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    
        <application
            android:name=".KaleApplication"
            android:allowBackup="true"
            android:label="@string/app_name">
            <activity
                android:name=".photo.GetSimplePhotoActivity"
                android:theme="@android:style/Theme.Translucent" />
        </application>
    
    
    </manifest>

    最后你可以仿照最上面的例子进行编码啦。

    源码下载:

    http://download.csdn.net/detail/shark0017/8671823

    新版的demo(推荐):http://download.csdn.net/detail/shark0017/8686807

  • 相关阅读:
    leetcode题目19.删除链表的倒数第N个节点(中等)
    Android学习笔记---使用Service模仿下载效果
    Android学习笔记-简单聊天界面的实现
    Android学习笔记-ContentProvider操作
    Android高级-Android操作SQL数据管理,增删改查
    Android高级-正则表达式
    Android高级-SQL语言
    Android学习之路-录音功能实现
    gitee上传下载代码命令
    opencv进行视频播放每帧处理,读取视频失败
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/4460811.html
Copyright © 2011-2022 走看看