关于调用手机图库选择图片的问题

  前段时间学习了《第一行代码》的书,然后照着写了一遍调用手机图库的方法,发现怎么也不成功,于是查阅资料和查看作者郭霖的博客后,发现了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),所以可能与书本有所差异。读者切勿直接拷贝。应在理解的基础上进行代码编写。

猜你喜欢

转载自bill56.iteye.com/blog/2305322