Android——从相机/相册获取图片

从相机获取图片

  • 设置权限
xml 复制代码
    <uses-permission android:name="android.permission.CAMERA" />
  • 点击跳转
java 复制代码
    private static final int REQUEST_CODE_TAKE = 1;
java 复制代码
    public void takePhoto(View view) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            doTake();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_TAKE);
        }
    }
  • 权限结果回调
java 复制代码
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_TAKE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                doTake();
            } else {
                Toast.makeText(this, "你没有获得摄像头权限", Toast.LENGTH_SHORT).show();
            }
        }
    }
java 复制代码
        register = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
            if (result != null) {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    try {
                        InputStream inputStream = getContentResolver().openInputStream(imageUri);
                        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                        // 转成Base64字符串 方便上传到服务器
                        imageBase64 = ImageUtil.imageToBase64(bitmap);
                        ivAvatar.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
  • 在 onCreate 中注册 Activity 返回结果回调
java 复制代码
    private void doTake() {
        File imageTemp = new File(getExternalCacheDir(), "imageOut.jpeg");
        if (imageTemp.exists()) {
            imageTemp.delete();
        }

        try {
            imageTemp.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        imageUri = Uri.fromFile(imageTemp);
        if (Build.VERSION.SDK_INT > 24) {
            imageUri = FileProvider.getUriForFile(this, "com.example.study_android.fileprovider", imageTemp);
        }
        Intent intent = new Intent();
        intent.setAction("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        register.launch(intent);
    }
  • 设置provider
xml 复制代码
        <provider
            android:authorities="com.example.study_android.fileprovider"
            android:name="androidx.core.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/files"/>
        </provider>
  • @xml/files
xml 复制代码
	<paths xmlns:android="http://schemas.android.com/apk/res/android">
	<external-path
	    name="image_path"
	    path="/"/>
	</paths>

从相册获取图片

  • 设置权限
xml 复制代码
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • 打开相册(需判断权限)
java 复制代码
    public void choosePhoto(View view) {
        // 权限WRITE_EXTERNAL_STORAGE表示同时授予程序对SD卡读和写的能力。
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            openAlbum();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_CHOOSE);
        }
    }

    private void openAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        registerAlbum.launch(intent);
    }
  • 注册相册返回结果回调
java 复制代码
        registerAlbum = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
            if (result != null) {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    Intent intent = result.getData();

                    if (Build.VERSION.SDK_INT < 19) {
                        handleImageBeforeApi19(intent);
                    } else {
                        handleImageOnApi19(intent);
                    }
                }
            }
        });
java 复制代码
    private void handleImageBeforeApi19(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagePath(uri, null);
        displayImage(imagePath);
    }
java 复制代码
    /*
     * 因为Android系统从4.4版本开始,选取相册中的图片不再返回图片真实的Uri了,而是一个封装过的Uri
     * 因此如果是4.4版本以上的手机就需要对这个Uri进行解析才行
     * */
    @TargetApi(19)
    private void handleImageOnApi19(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();

        if (DocumentsContract.isDocumentUri(this, uri)) {
            // 如果是document类型的Uri,则通过document id处理
            String documentId = DocumentsContract.getDocumentId(uri);

            if (TextUtils.equals(uri.getAuthority(), "com.android.providers.media.documents")) {
                String id = documentId.split(":")[1];
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);

            } else if (TextUtils.equals(uri.getAuthority(), "com.android.providers.downloads.documents")) {
                if (documentId != null && documentId.startsWith("msf:")) {
                    resolveMSFContent(uri);
                    return;
                }
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId));
                imagePath = getImagePath(contentUri, null);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // 如果是content类型的Uri,则使用普通方式处理
            imagePath = getImagePath(uri, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            // 如果是file类型的Uri,直接获取图片路径
            imagePath = uri.getPath();
        }
        displayImage(imagePath);
    }
java 复制代码
    private void resolveMSFContent(Uri uri) {
        File file = new File(getCacheDir(), "temp_file" + getContentResolver().getType(uri).split("/")[1]);
        try {
            InputStream inputStream = getContentResolver().openInputStream(uri);
            OutputStream outputStream = new FileOutputStream(file);
            byte[] buffer = new byte[4 * 1024];
            int read;
            while ((read = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, read);
            }
            outputStream.flush();
            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
            ivAvatar.setImageBitmap(bitmap);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
java 复制代码
    // 获取图片真实路径
    @SuppressLint("Range")
    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;
    }

案例代码

相关推荐
阿甘知识库35 分钟前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道1 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
居居飒2 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He5 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗5 小时前
Android笔试面试题AI答之Android基础(1)
android
qq_397562317 小时前
android studio更改应用图片,和应用名字。
android·ide·android studio
峥嵘life7 小时前
Android Studio版本升级那些事
android·ide·android studio
新手上路狂踩坑7 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
TroubleMaker9 小时前
OkHttp源码学习之retryOnConnectionFailure属性
android·java·okhttp
叶羽西11 小时前
Android Studio IDE环境配置
android·ide·android studio