首先配置一下我们的项目
(1)在build.gradle里添加类库:
compile 'de.hdodenhof:circleimageview:2.0.0'
(2)设置清单文件
2.1、在清单文件里面添加权限
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
2.2、在清单文件里面添加provider
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.zz.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>(3)在res目录下,新建一个xml文件夹,在xml文件夹里面,新建一个文件:file_paths.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <paths> <external-path name="camera_photos" path="" /> </paths> </resources>
(4)新建布局文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/photo" android:layout_width="150dp" android:layout_height="150dp" android:layout_centerHorizontal="true" android:src="@mipmap/a1"/> <Button android:id="@+id/takePic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/photo" android:text="打开相机" android:layout_marginTop="50dp" android:layout_centerHorizontal="true"/> <Button android:id="@+id/takeGallery" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/takePic" android:layout_marginTop="20dp" android:text="打开相册" android:layout_centerHorizontal="true"/> </RelativeLayout>
(5)在MainActivity中调用方法
//参考网址 https://github.com/zhengzhong1/Android6.0PermissionsDemo
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private CircleImageView photo; private Button takePic; private Button takeGallery; private static final int CODE_GALLERY_REQUEST = 0xa0; private static final int CODE_CAMERA_REQUEST = 0xa1; private static final int CODE_RESULT_REQUEST = 0xa2; private static final int CAMERA_PERMISSIONS_REQUEST_CODE = 0x03; private static final int STORAGE_PERMISSIONS_REQUEST_CODE = 0x04; private File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/photo.jpg"); private File fileCropUri = new File(Environment.getExternalStorageDirectory().getPath() + "/crop_photo.jpg"); private Uri imageUri; private Uri cropImageUri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_name); photo = (CircleImageView)findViewById(R.id.photo); takePic = (Button)findViewById(R.id.takePic); takeGallery = (Button)findViewById(R.id.takeGallery); takePic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { autoObtainCameraPermission(); } }); takeGallery.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { autoObtainStoragePermission(); } }); } /** * 自动获取相机权限 */ private void autoObtainCameraPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { ToastUtils.showShort(this, "您已经拒绝过一次"); } ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE}, CAMERA_PERMISSIONS_REQUEST_CODE); } else {//有权限直接调用系统相机拍照 if (hasSdcard()) { imageUri = Uri.fromFile(fileUri); //通过FileProvider创建一个content类型的Uri if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { imageUri = FileProvider.getUriForFile(MainActivity.this, "com.zz.fileprovider", fileUri); } PhotoUtils.takePicture(this, imageUri, CODE_CAMERA_REQUEST); } else { ToastUtils.showShort(this, "设备没有SD卡!"); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { //调用系统相机申请拍照权限回调 case CAMERA_PERMISSIONS_REQUEST_CODE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (hasSdcard()) { imageUri = Uri.fromFile(fileUri); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) imageUri = FileProvider.getUriForFile(MainActivity.this, "com.zz.fileprovider", fileUri);//通过FileProvider创建一个content类型的Uri PhotoUtils.takePicture(this, imageUri, CODE_CAMERA_REQUEST); } else { ToastUtils.showShort(this, "设备没有SD卡!"); } } else { ToastUtils.showShort(this, "请允许打开相机!!"); } break; } //调用系统相册申请Sdcard权限回调 case STORAGE_PERMISSIONS_REQUEST_CODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { PhotoUtils.openPic(this, CODE_GALLERY_REQUEST); } else { ToastUtils.showShort(this, "请允许打操作SDCard!!"); } break; default: } } private static final int OUTPUT_X = 480; private static final int OUTPUT_Y = 480; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { switch (requestCode) { //拍照完成回调 case CODE_CAMERA_REQUEST: cropImageUri = Uri.fromFile(fileCropUri); PhotoUtils.cropImageUri(this, imageUri, cropImageUri, 1, 1, OUTPUT_X, OUTPUT_Y, CODE_RESULT_REQUEST); break; //访问相册完成回调 case CODE_GALLERY_REQUEST: if (hasSdcard()) { cropImageUri = Uri.fromFile(fileCropUri); Uri newUri = Uri.parse(PhotoUtils.getPath(this, data.getData())); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { newUri = FileProvider.getUriForFile(this, "com.zz.fileprovider", new File(newUri.getPath())); } PhotoUtils.cropImageUri(this, newUri, cropImageUri, 1, 1, OUTPUT_X, OUTPUT_Y, CODE_RESULT_REQUEST); } else { ToastUtils.showShort(this, "设备没有SD卡!"); } break; case CODE_RESULT_REQUEST: Bitmap bitmap = PhotoUtils.getBitmapFromUri(cropImageUri, this); if (bitmap != null) { showImages(bitmap); } break; default: } } } /** * 自动获取sdk权限 */ private void autoObtainStoragePermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSIONS_REQUEST_CODE); } else { PhotoUtils.openPic(this, CODE_GALLERY_REQUEST); } } private void showImages(Bitmap bitmap) { photo.setImageBitmap(bitmap); } /** * 检查设备是否存在SDCard的工具方法 */ public static boolean hasSdcard() { String state = Environment.getExternalStorageState(); return state.equals(Environment.MEDIA_MOUNTED); } }
(5)Toast统一管理类
public class ToastUtils { private ViewGroup.LayoutParams layoutParams; private ToastUtils() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } public static boolean isShow = true; /** * 短时间显示Toast * * @param context * @param message */ public static void showShort(Context context, CharSequence message) { if (isShow) Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); } /** * 短时间显示Toast * * @param context * @param message */ public static void showShort(Context context, int message) { if (isShow) Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); } /** * 长时间显示Toast * * @param context * @param message */ public static void showLong(Context context, CharSequence message) { if (isShow) Toast.makeText(context, message, Toast.LENGTH_LONG).show(); } /** * 长时间显示Toast * * @param context * @param message */ public static void showLong(Context context, int message) { if (isShow) Toast.makeText(context, message, Toast.LENGTH_LONG).show(); } /** * 自定义显示Toast时间 * * @param context * @param message * @param duration */ public static void show(Context context, CharSequence message, int duration) { if (isShow) Toast.makeText(context, message, duration).show(); } /** * 自定义显示Toast时间 * * @param context * @param message * @param duration */ public static void show(Context context, int message, int duration) { if (isShow) Toast.makeText(context, message, duration).show(); } }(6)图片处理类 PhotoUtils
public class PhotoUtils { private static final String TAG = "PhotoUtils"; /** * @param activity 当前activity * @param imageUri 拍照后照片存储路径 * @param requestCode 调用系统相机请求码 */ public static void takePicture(Activity activity, Uri imageUri, int requestCode) { //调用系统相机 Intent intentCamera = new Intent(); intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE); //将拍照结果保存至photo_file的Uri中,不保留在相册中 intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); activity.startActivityForResult(intentCamera, requestCode); } /** * @param activity 当前activity * @param requestCode 打开相册的请求码 */ public static void openPic(Activity activity, int requestCode) { Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT); photoPickerIntent.setType("image/*"); activity.startActivityForResult(photoPickerIntent, requestCode); } /** * @param activity 当前activity * @param orgUri 剪裁原图的Uri * @param desUri 剪裁后的图片的Uri * @param aspectX X方向的比例 * @param aspectY Y方向的比例 * @param width 剪裁图片的宽度 * @param height 剪裁图片高度 * @param requestCode 剪裁图片的请求码 */ public static void cropImageUri(Activity activity, Uri orgUri, Uri desUri, int aspectX, int aspectY, int width, int height, int requestCode) { Intent intent = new Intent("com.android.camera.action.CROP"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } intent.setDataAndType(orgUri, "image/*"); //发送裁剪信号 intent.putExtra("crop", "true"); intent.putExtra("aspectX", aspectX); intent.putExtra("aspectY", aspectY); intent.putExtra("outputX", width); intent.putExtra("outputY", height); intent.putExtra("scale", true); //将剪切的图片保存到目标Uri中 intent.putExtra(MediaStore.EXTRA_OUTPUT, desUri); //1-false用uri返回图片 //2-true直接用bitmap返回图片(此种只适用于小图片,返回图片过大会报错) intent.putExtra("return-data", false); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); activity.startActivityForResult(intent, requestCode); } /** * 读取uri所在的图片 * * @param uri 图片对应的Uri * @param mContext 上下文对象 * @return 获取图像的Bitmap */ public static Bitmap getBitmapFromUri(Uri uri, Context mContext) { try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), uri); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } } /** * @param context 上下文对象 * @param uri 当前相册照片的Uri * @return 解析后的Uri对应的String */ @SuppressLint("NewApi") public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; String pathHead = "file:///"; // 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 pathHead + 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 pathHead + 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 pathHead + getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { return pathHead + getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return pathHead + 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 column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_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()); } }