Android通过系统相机和相册设置头像

来源:互联网 发布:草木知春不久归下一句 编辑:程序博客网 时间:2024/05/21 04:19

本文主要讲解通过Android相机和相册设置头像的技巧和问题,虽然网上有很多相关的例子和讲解,不过还是有很多坑需要填补。

  1. Intent传值不能太大,超过内存限制后Intent的getData()方法会返回null,造成的后果就是裁剪完图片看不到结果。因为现在手机的相机像素都比较高所以造成相机拍摄完的图片size都比较大。

    对于第一种情况,可以使用本地保存图片的方法,先把从相机拍摄得图片保存在本地,然后再进行裁剪。先看一下用相机拍摄照片的方法:

 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); String mCurrentPhotoName = System.currentTimeMillis() + ".jpg";                intent.putExtra(MediaStore.EXTRA_OUTPUT,                        Uri.fromFile(new File(Environment.getExternalStorageDirectory(), mCurrentPhotoName)));                startActivityForResult(intent, CODE_REQUEST_CAMERA_PHOTO);
MediaStore.EXTRA_OUTPUT

这个Key是用来设置拍摄图片完成后储存的位置。

拍照完成后代码会执行到onActivityResult方法中(如果在Fragment里执行的话需要覆盖Activity的onActivityResult方法,并在Activity中的onActivityResult方法中调用Fragment的onActivityResult方法)。

@Override    public void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if(requestCode == CODE_REQUEST_CAMERA_PHOTO){            if(resultCode == Activity.RESULT_OK){                if(data == null) {                    FilesUtil.deleteFiles(Environment.getExternalStorageDirectory() + File.separator + mCurrentPhotoName);                    return;                }                File tempFile = new File(                        Environment.getExternalStorageDirectory(),                        mCurrentPhotoName);                mNewCurrentPhotoName = "pz_" + mCurrentPhotoName;                String outPath = Environment.getExternalStorageDirectory() + File.separator + mNewCurrentPhotoName;                CropPhotoUtil.cropRawPhoto(getActivity(), Uri.fromFile(tempFile), CODE_REQUEST_CROP_PHOTO, outPath, 200, 200);            }else{//如果没有成功把拍摄的图片删除,删除文件的方法请百度             FilesUtil.deleteFiles(Environment.getExternalStorageDirectory()+ File.separator  + mCurrentPhotoName);            }        }}

CODE_REQUEST_CAMERA_PHOTO 就是拍照时设置的返回码,只要一致即可。
CropPhotoUtil.cropRawPhoto()方法是剪切图片的方法,看下面:

package com.bibi.mark.takepicture;import android.app.Activity;import android.content.ContentUris;import android.content.Context;import android.content.Intent;import android.database.Cursor;import android.net.Uri;import android.os.Build;import android.os.Environment;import android.provider.DocumentsContract;import android.provider.MediaStore;import android.widget.Toast;import java.io.File;import java.io.FileNotFoundException;/** * 剪切相机或者相册图片的工具类 * Created by mark on 16/4/1. */public class CropPhotoUtil {    /**     *     * 裁剪原始的图片     * @param activity     * @param uri 输入的URI     * @param requestCode 收到消息的返回码     * @param outPath 输入的文件地址     * @param output_X 宽     * @param output_Y 高     *     */    public static void cropRawPhoto(Activity activity, Uri uri, int requestCode, String outPath, int output_X, int output_Y) {        if (uri == null) {            Toast.makeText(activity,"截取图片错误",Toast.LENGTH_SHORT).show();            return;        }        try {            Intent intent = new Intent("com.android.camera.action.CROP");            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {                String url = getPath(activity, uri);                intent.setDataAndType(Uri.fromFile(new File(url)), "image/*");            }else{                intent.setDataAndType(uri, "image/*");            }            intent.putExtra("crop", true);            intent.putExtra("aspectX", 1);            intent.putExtra("aspectY", 1);            intent.putExtra("outputX", output_X);            intent.putExtra("outputY", output_Y);            intent.putExtra("return-data", false);            Uri uritempFile = Uri.fromFile(new File(outPath));            intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);            activity.startActivityForResult(intent, requestCode);        } catch (Exception e) {            e.printStackTrace();            Toast.makeText(activity,"截取图片错误",Toast.LENGTH_SHORT).show();        }    }    private 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];                }            }            // 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());    }    /**     * 往相册插入照片     */    public static String insertImage(Activity activity,String imagePath, String name) {        try {            String path = MediaStore.Images.Media.insertImage(activity.getContentResolver(), imagePath, name, "");            return  path;        } catch (FileNotFoundException e) {            e.printStackTrace();        }        return null;    }    /**     * 存储完照片记得扫描相册     * @param activity     */    public static void searchMedia(Activity activity){        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);        Uri uri = Uri.fromFile(new File("/sdcard/image.jpg"));        intent.setData(uri);        activity.sendBroadcast(intent);    }    /**     * 获取存储到相册后的图片地址     * @param context     * @param uri     * @return     */    private String getFilePathByContentResolver(Context context, Uri uri) {        if (null == uri) {            return null;        }        Cursor c = context.getContentResolver().query(uri, null, null, null, null);        String filePath  = null;        if (null == c) {            throw new IllegalArgumentException(                    "Query on " + uri + " returns null result.");        }        try {            if ((c.getCount() != 1) || !c.moveToFirst()) {            } else {                filePath = c.getString(                        c.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));            }        } finally {            c.close();        }        return filePath;    }}

这个是剪切图片的工具类方法。
2. 上面展示了第二个坑就剪切图片的时候在Android4.4之后传Uri的格式问题,经过上面代码的getPath()方法已经转成Intent可以识别的Uri,即可跳转到剪切页面。

顺便写下从相册读取图片的代码

Intent intentFromGallery = new Intent();                intentFromGallery.setType("image/*");//选择图片                intentFromGallery.setAction(Intent.ACTION_GET_CONTENT);                startActivityForResult(intentFromGallery, CODE_REQUEST_PICTURE);

在onActivityResult方法中监听CODE_REQUEST_PICTURE这个返回值时调用剪切图片的工具方法跳转到剪切页面即可。

说下在剪切完成后怎么读取图片,因为没有用Intent传值的方式来传递Bitmap,都是通过文件的存储路径来读取图片,所以可以用自定义的路径来读取出Bitmap。然后设置头像即可。
另附上源码地址:https://github.com/MarkSunDev/TakePicture

0 0