最近项目中有用到拍照与相册选择照片并保存本地的操作,在网上查看了很多的例子,然后进行了总结,还算基本满足了自己的需求,所以今天在这里做一个总结,将相关知识点总结出来免得忘记(人老了记性不好 =。=)。
这个Demo的布局非常简单,就是两个TextView来表示拍照按钮和选择相册按钮,一个ImageView来显示选择的照片,所以布局文件在这里就不贴出了,我们将java代码贴出来:
要用到的一些状态信息,这个可以自己设置就好:
private static String IMAGE_FILE_NAME = System.currentTimeMillis()+".jpg";/*** 请求不同状态的状态码*/private static final int IMAGE_REQUEST_CODE = 0;private static final int SELECT_PIC_KITKAT = 3;private static final int CAMERA_REQUEST_CODE = 1;private static final int RESULT_REQUEST_CODE = 2;
这是点击事件所执行的方法:
<span style="font-size:18px;">@butterknife.OnClick({R.id.tv1, R.id.tv2})public void onClick(View view) {switch (view.getId()) {case R.id.tv1:/*** 点击照相*/Intent intentFromCapture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 判断存储卡是否可以用,可用进行存储intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(new File(Environment.getExternalStorageDirectory(),IMAGE_FILE_NAME)));startActivityForResult(intentFromCapture,CAMERA_REQUEST_CODE);break;case R.id.tv2:/*** 点击相册*/Intent intent1 = new Intent(Intent.ACTION_GET_CONTENT);intent1.addCategory(Intent.CATEGORY_OPENABLE);intent1.setType("image/*");if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {startActivityForResult(intent1, SELECT_PIC_KITKAT);} else {startActivityForResult(intent1, IMAGE_REQUEST_CODE);}break;}}</span>
这是onActivityResult中实现的:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode) {case 1:if (resultCode == 2) {}break; }// 结果码不等于取消时候 if (resultCode != this.RESULT_CANCELED) {switch (requestCode) {case IMAGE_REQUEST_CODE:startPhotoZoom(data.getData()); break; case SELECT_PIC_KITKAT://图库 if(data!=null)bitmapFactory(data.getData()); break; case CAMERA_REQUEST_CODE://照相机 String sdStatus = Environment.getExternalStorageState(); // 检测sd是否可用 if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) {Toast.makeText(this,"内存卡异常,请检查内存卡插入是否正确",Toast.LENGTH_SHORT).show(); return; }File tempFile = new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME); startPhotoZoom(Uri.fromFile(tempFile)); break; case RESULT_REQUEST_CODE:setImageToView(data); break; }} }
其他相关的方法:
<span style="font-size:18px;">/*** 裁剪图片方法实现** @param uri*/public void startPhotoZoom(Uri uri) {if (uri == null) {Log.e("TAG", "The uri is not exist.");return;}Intent intent = new Intent("com.android.camera.action.CROP");if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {String url = getPath(this.getApplication(), uri);intent.setDataAndType(Uri.fromFile(new File(url)), "image/*");} else {intent.setDataAndType(uri, "image/*");}// 设置裁剪intent.putExtra("crop", "true");// aspectX aspectY 是宽高的比例intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1);// outputX outputY 是裁剪图片宽高intent.putExtra("outputX", 300);intent.putExtra("outputY", 300);intent.putExtra("return-data", true);startActivityForResult(intent, RESULT_REQUEST_CODE);}/*** 图库的照片选择过后加载到ImageView* @param uri*/private void bitmapFactory(Uri uri){Log.e("----","uri:"+uri.toString());String filepath= getPath(this,uri);if(!TextUtils.isEmpty(filepath)){filepath="file:///"+filepath;ImageLoader.getInstance().displayImage(filepath,iv);}}/*** 保存照片并设置照片给对应的View* @param data*/private void setImageToView(Intent data) {Bundle extras = data.getExtras();if (extras != null) {Bitmap photo = extras.getParcelable("data");String path=saveBitmap(photo);setPicture(path);
// iv.setImageBitmap(BitmapFactory.decodeFile(path));}}/*** 给控件设置图片* @param path*/public void setPicture(String path){path="file:///"+path;ImageLoader.getInstance().displayImage(path,iv);}/*** 创建保存图片的文件夹*/public void createFile(){String path=Environment.getExternalStorageDirectory()+"/myphoto/";File f=new File(path);if(!f.exists()){f.mkdir();}}/*** 保存照片* @param mBitmap* @return*/public String saveBitmap(Bitmap mBitmap) {String sdStatus = Environment.getExternalStorageState();if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用Toast.makeText(this,"内存卡异常,请检查内存卡插入是否正确",Toast.LENGTH_SHORT).show();return "";}String path=System.currentTimeMillis()+".jpg";File f = new File(Environment.getExternalStorageDirectory()+"/myphoto/",path);createFile();try {FileOutputStream fOut = null;fOut = new FileOutputStream(f);mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);fOut.flush();fOut.close();return f.getAbsolutePath();} catch (Exception e) {e.printStackTrace();return null;}}//Ps:原本uri返回的是file:///...,android4.4返回的是content://,所以这里要注意一下@TargetApi(Build.VERSION_CODES.KITKAT)public String getPath(final Context context, final Uri uri) {final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;// DocumentProviderif (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {// ExternalStorageProviderif (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];}}// DownloadsProviderelse 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);}// MediaProviderelse 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 addressif (isGooglePhotosUri(uri))return uri.getLastPathSegment();return getDataColumn(context, uri, null, null);}// Fileelse if ("file".equalsIgnoreCase(uri.getScheme())) {return uri.getPath();}return null;}public 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;}public static boolean isExternalStorageDocument(Uri uri) {return "com.android.externalstorage.documents".equals(uri.getAuthority());}public static boolean isDownloadsDocument(Uri uri) {return "com.android.providers.downloads.documents".equals(uri.getAuthority());}public static boolean isMediaDocument(Uri uri) {return "com.android.providers.media.documents".equals(uri.getAuthority());}public static boolean isGooglePhotosUri(Uri uri) {return "com.google.android.apps.photos.content".equals(uri.getAuthority());}</span>
这样我们就可以根据照相和相册选择来显示不同路径的图片了,在Demo中我们图片的显示加载用了ImageLoader,因为这个不是我们这一次的重点所以代码就不贴出来了,需要了解的朋友自己去查一查相关的博客吧,在Demo中我们可能用到的权限如下:
<span style="font-size:18px;"><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><!--往sdcard中写入数据的权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission><!--在sdcard中创建/删除文件的权限 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission><uses-permission android:name="android.permission.CAMERA"></uses-permission></span>
---------------END!