Android通过系统相机和相册设置头像
来源:互联网 发布:草木知春不久归下一句 编辑:程序博客网 时间:2024/05/21 04:19
本文主要讲解通过Android相机和相册设置头像的技巧和问题,虽然网上有很多相关的例子和讲解,不过还是有很多坑需要填补。
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
- Android通过系统相机和相册设置头像
- android通过相册、相机设置头像
- 调用系统相册,相机设置圆形头像
- Android头像上传(本地相册和调用系统相机)
- android调用手机相机、相册,设置头像
- android选择系统相机拍照和系统相册,裁剪图片并保存和设置头像,适配至7.0
- Android中通过访问本地相册或者相机设置用户头像
- android 调用系统图库和相机设置头像
- iOS开发swift如何调用系统相册和相机获取图片设置用户头像
- 【iOS】一个完整的简单的调用系统相机和相册设置头像
- Android通过访问相机或相册来更换头像
- android读取系统相册,设置头像
- Android调用系统相机或相册更换头像
- Android 相册和拍照设置头像功能
- 调用系统相机相册上传头像
- 调用系统相机/相册,实现更改头像
- Android 跳转到系统相机和相册
- android 调用系统相机和相册
- USACO 1.1-gift1
- 树莓派网线直连笔记本电脑
- bash: ./arm-none-linux-gnueabi-gcc: No such file or directory解决方法
- Android图形graphics--自定义TextView,onMeasure和onDraw
- 【Android开发】开源库AndroidSlidingUpPanel详解
- Android通过系统相机和相册设置头像
- USACO 1.1-ride
- Android手机摇杆
- linux 下 按 ctrl + s 锁屏
- USACO 1.2-Dual Palindromes
- openwrt pcm driver on mt7620 or rt5350
- C++实验-标准体重
- Java NIO系列教程(一) Java NIO 概述
- USACO 1.2-Milking Cows