关于调用手机图库选择图片的有关问题
关于调用手机图库选择图片的问题
前段时间学习了《第一行代码》的书,然后照着写了一遍调用手机图库的方法,发现怎么也不成功,于是查阅资料和查看作者郭霖的博客后,发现了android在API19以前和之后的方式不一样,特此进行记载。方便日后的学习。
一、活动中选择相机和图片的处理方法
/** * 实现了点击事件监听器的自定义按钮点击类,用于监听按钮点击的事件 */ class OnButtonListener implements View.OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { // 点击的选择图片 case R.id.btn_selpic: doSelpic(); break; // 点击的拍照 case R.id.btn_takeaphoto: doTakeaphoto(); break; default: break; } } /** * 点击选择图片按钮后执行的代码 */ private void doSelpic() { // 获取设备的根目录 File sdDir = Environment.getExternalStorageDirectory(); // 创建缓存目录 File cacheDir = new File(sdDir, "UPhotocache"); // 如果不存在目录,则创建 if (!cacheDir.exists()) { cacheDir.mkdir(); } // 创建File对象,用于存储牌照后的图片 outputImage = new File(cacheDir, "output_image.jpg"); try { // 如果存在则删除 if (outputImage.exists()) { outputImage.delete(); } // 创建一个新的文件 outputImage.createNewFile(); } catch (IOException e) { e.printStackTrace(); } // 启动选择图片的活动 imageUri = Uri.fromFile(outputImage); Intent intent = new Intent("android.intent.action.GET_CONTENT"); intent.setType("image/*"); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, CHOOSE_FROM_ALBUM); } /** * 点击拍照按钮后执行的代码 */ private void doTakeaphoto() { // 获取设备的根目录 File sdDir = Environment.getExternalStorageDirectory(); // 创建缓存目录 File cacheDir = new File(sdDir, "UPhotocache"); // 如果不存在目录,则创建 if (!cacheDir.exists()) { cacheDir.mkdir(); } // 创建File对象,用于存储牌照后的图片 outputImage = new File(cacheDir, "output_image.jpg"); try { // 如果存在则删除 if (outputImage.exists()) { outputImage.delete(); } // 创建一个新的文件 outputImage.createNewFile(); } catch (IOException e) { e.printStackTrace(); } imageUri = Uri.fromFile(outputImage); // 更新保存的路径 imageSelPath = outputImage.getAbsolutePath(); // 启动拍照程序 Intent takeIntent = new Intent("android.media.action.IMAGE_CAPTURE"); takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); // 设置回传的请求码 startActivityForResult(takeIntent, TAKE_PHOTO); } }
二、回传结果后调用的方法逻辑代码
/** * 当选择的活动回传数据的时候调用 * * @param requestCode 请求码 * @param resultCode 结果码 * @param data 数据 */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // 根据请求码处理不同的返回结果 switch (requestCode) { case TAKE_PHOTO: // 当拍照程序返回结果为正确的时候 if (resultCode == RESULT_OK) { // 调用剪裁程序活动 Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(imageUri, "image/*"); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, CROP_PHOTO); } break; case CHOOSE_FROM_ALBUM: // 当选择照片正确返回的时候 if (resultCode == RESULT_OK) { //判断手机系统的版本号 if (Build.VERSION.SDK_INT >= 19) { handleImageOnKitKat(data); } else { handleImageBeforeKitkat(data); } } break; case CROP_PHOTO: // 当剪裁程序返回的结果是正确的时候 if (resultCode == RESULT_OK) { // 将剪裁后的图片的路径传递给编辑图片的活动 Intent editIntent = new Intent(this, EditPicActivity.class); editIntent.putExtra("EDIT_PIC", imageSelPath); startActivity(editIntent); } break; default: break; } }
三、判断版本不同进行的图片选择代码
/** * 当系统为4.4以上版本的时候,必须以以下方式才可以读取图片 * * @param data 回传的intent对象 */ @TargetApi(19) private void handleImageOnKitKat(Intent data) { String imagePath = null; Uri uri = data.getData(); imageUri = uri; if (DocumentsContract.isDocumentUri(this, uri)) { LogUtil.d("YYW", "获得了图片的Uri信息"); // 如果文档类型是uri,则通过document id 处理 String docId = DocumentsContract.getDocumentId(uri); if ("com.android.providers.media.documents".equals(uri .getAuthority())) { String id = docId.split(":")[1]; String selection = MediaStore.Images.Media._ID + "=" + id; imagePath = getImagePath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection); LogUtil.d("YYW", "com.android.providers.media.documents"); } else if ("com.android.providers.downloads.documents".equals(uri .getAuthority())) { Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); imagePath = getImagePath(contentUri, null); LogUtil.d("YYW", "com.android.providers.downloads.documents"); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { // 如果不是document类型的Uri,则使用普通方式处理 imagePath = getImagePath(uri, null); LogUtil.d("YYW", "content"); } else { LogUtil.d("YYW", "未知类型"); } imageSelPath = imagePath; displayImage(imageSelPath); } /** * 当系统为4.4以下的时候必须以以下方式读取图片 * * @param data 回传的intent对象 */ private void handleImageBeforeKitkat(Intent data) { Uri uri = data.getData(); imageUri = uri; imageSelPath = getImagePath(uri, null); displayImage(imageSelPath); } /** * 获得选择的图片的真实路径 * * @param uri 图片的标识符 * @param selection 选择的选项,可为空 * @return 选择的图片的真实路径 */ private String getImagePath(Uri uri, String selection) { String path = null; //通过Uri跟selection来获取真实的图片路径 Cursor cursor = getContentResolver().query(uri, null, selection, null, null); if (cursor != null) { if (cursor.moveToFirst()) { path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); } cursor.close(); } return path; } /** * 将图片传递给编辑活动的方法 * * @param imagePath 图片路径 */ private void displayImage(String imagePath) { if (imagePath != null) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(imageUri, "image/*"); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, CROP_PHOTO); } else { ToastUtil.show(this, R.string.fail_get_image); } }
注意:
由于我需要实现的功能为:通过拍照或者选择图片后将其传递到另一个活动(EditPicActivity),所以可能与书本有所差异。读者切勿直接拷贝。应在理解的基础上进行代码编写。