Android 使用 registerForActivityResult() 打开系统相册或相机获取图像

这篇具有很好参考价值的文章主要介绍了Android 使用 registerForActivityResult() 打开系统相册或相机获取图像。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简介

当使用了 AndroidX 后,发现 `startActivityForResult()` 标记为过时了,而是推荐我们使用 `registerForActivityResult()` 函数。

`registerForActivityResult()` 函数是 Android 中用于启动 Activity 结果回调的新方式。这个函数的目的是简化在 Activity 和 Fragment 之间进行启动其他 Activity 并接收结果的过程,取代了传统的 `startActivityForResult()``onActivityResult()` 方法。

使用 `registerForActivityResult()` 函数,您可以更容易地管理 Activity 结果的处理,使代码更清晰和模块化。

AndroidX 介绍:

AndroidX 是 Android 中的一个开发库,旨在简化 Android 应用程序的开发和维护。AndroidX 提供了一组替代 Android Support Library 的库,它们包括了新的功能、改进的性能和更好的兼容性,以便开发人员更轻松地构建现代化、高质量的 Android 应用程序。

主要包括:

  1. 新功能和改进: AndroidX 引入了许多新的功能和改进,包括更好的 Jetpack 组件、性能优化、Kotlin 支持、Android 架构组件等,以提高开发效率和用户体验。
  2. 向后兼容性: AndroidX 专注于提供向后兼容性,以确保应用程序在不同 Android 版本上能够稳定运行。这意味着即使您的应用使用了 AndroidX 库,也可以在较旧的 Android 版本上运行。
  3. Jetpack 组件: AndroidX 包括了 Android Jetpack 组件,这是一组库和工具,旨在简化 Android 应用程序的常见开发任务,例如导航、数据存储、UI 构建、生命周期管理等。Jetpack 组件的目标是提高应用程序的可维护性、稳定性和性能。

二、打开相册获取图像

1. 代码示例

public class MainActivity extends AppCompatActivity {
    
    private ActivityResultLauncher<String> mGalleryLauncher;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 需要事先注册
        mGalleryLauncher = registerForActivityResult(
                // 获取内容,回调函数的参数将是一个URI
                new ActivityResultContracts.GetContent(),
                // 回调函数
                this::handleGalleryResult);
    }
    
    private void openGallery() {
        if (mGalleryLauncher != null) {
            // launch的输入参数是泛型,对应ActivityResultLauncher<String>
            mGalleryLauncher.launch("image/*");
        }
    }
    
    private void handleGalleryResult(Uri imageUri) {
        if (imageUri != null) {
            try {
                Bitmap selectedBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
                int rotation = ImageUtil.getRotation(this, imageUri);
                Bitmap rotatedBitmap = ImageUtil.rotateBitmap(selectedBitmap, rotation);
                // 后续处理逻辑
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2. ImageUtil部分函数

public static Bitmap rotateBitmap(Bitmap bitmap, int rotation) {
    if (rotation == 0) {
        return bitmap;
    }
    return rotateResizeBitmap(bitmap, rotation, 1f);
}

public static Bitmap rotateResizeBitmap(Bitmap source, float angle, float scale) {
    Matrix matrix = new Matrix();
    matrix.postRotate(angle);
    if (scale != 1f) {
        matrix.setScale(scale, scale);
    }
    return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}

public static int getRotation(Context context, Uri photoUri) {
    if (photoUri == null) {
        return 0;
    }
    ExifInterface ei;
    try {
        InputStream inputStream = context.getContentResolver().openInputStream(photoUri);
        ei = new ExifInterface(inputStream);
    } catch (IOException e) {
        return 0;
    }
    int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
    switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            return 90;
        case ExifInterface.ORIENTATION_ROTATE_180:
            return 180;
        case ExifInterface.ORIENTATION_ROTATE_270:
            return 270;
        default:
            return 0;
    }
}

三、打开相机获取图像

因为使用的是系统相机应用,所以也不需要额外申请相机权限了。

1. 代码示例

public class MainActivity extends AppCompatActivity {
    
    private ActivityResultLauncher<Intent> mCameraLauncher;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 需要事先注册
        mCameraLauncher = registerForActivityResult(
                // 回调函数的参数将是一个ActivityResult
                new ActivityResultContracts.StartActivityForResult(),
                // 回调函数
                this::handleCameraResult);
    }
    
    private void openCamera() {
        if (mCameraLauncher != null) {
            // launch的输入参数是泛型,对应ActivityResultLauncher<Intent>
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            // 确保有相机应用可用
            if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                mCameraLauncher.launch(takePictureIntent);
            }
        }
    }
    
    private void handleCameraResult(ActivityResult result) {
        if (result.getResultCode() == RESULT_OK) {
            Intent data = result.getData();
            if (data != null) {
                Bundle extras = data.getExtras();
                if (extras != null) {
                    Uri uri = data.getData();
                    Bitmap imageBitmap = (Bitmap) extras.get("data");
                    // 后续处理逻辑
                }
            }
        }
    }
}

注意:

由于Bundle本身能够携带的数据大小限制,上面这种方式获取的相机图像分辨率通常很低。如果希望能够获取较大分辨率的图像,则可以先将相机图像保存到本地,再通过文件路径加载。具体方式如下:

2. 修改openCamera()

在打开相机的Intent中添加一个文件输出的Uri,告诉相机需要保存到指定位置。

private String mPhotoPath; // 用于存储文件保存的路径

private void openCamera() {
    if (mCameraLauncher != null) {
        // launch的输入参数是泛型,对应ActivityResultLauncher<Intent>
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 确保有相机应用可用
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // 创建一个用于存储拍照结果的文件
            File photoFile = ImageUtil.createImageFile(this);
            mPhotoPath = photoFile.getAbsolutePath();
            Uri photoUri = FileProvider.getUriForFile(this,
                    "com.afei.demo.provider", // 对应 AndroidManifest.xml 中的声明
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
            mCameraLauncher.launch(takePictureIntent);
        }
    }
}

3. ImageUtil.createImageFile() 代码

创建一个可写的文件即可。

public static File createImageFile(Context context) {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date(System.currentTimeMillis()));
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    if (!storageDir.exists()) {
        storageDir.mkdirs();
    }
    File imageFile = null;
    try {
        imageFile = File.createTempFile(
                imageFileName,  /* 文件名 */
                ".jpg",         /* 文件扩展名 */
                storageDir      /* 存储目录 */
        );
        imageFile.setWritable(true);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return imageFile;
}

4. 自定义的FileProvider

上述代码中还使用到了一个 `FileProvider.getUriForFile()` 方法,作为四大组件之一,也是需要在 AndroidManifest.xml 文件中声明和使用的。

a. AndroidManifest.xml 文件中
<application>
    ...
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.afei.demo.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

authorities 通常可以用 `包名+.provider`

b. xml/file_paths 文件

res 文件夹下面创建一个 xml 子文件夹,并新建 file_paths.xml 文件(文件名可以修改,和AndroidManifest.xml中对应上就行),内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="my_images"
        path="." />
</paths>

关于FileProvider的使用这里不过多介绍了,不清楚的可以查阅其他资料。

5. 修改 handleCameraResult(ActivityResult result)

这里就不再需要通过 ActivityResult 获取数据了,而是从之前存储的 `mPhotoPath` 中获取。文章来源地址https://www.toymoban.com/news/detail-718924.html

private void handleCameraResult(ActivityResult result) {
    if (result.getResultCode() == RESULT_OK) {
        Bitmap bitmap = BitmapFactory.decodeFile(mPhotoPath);
        // 后续处理逻辑
    }
}

到了这里,关于Android 使用 registerForActivityResult() 打开系统相册或相机获取图像的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android---打开相册选择图片

    简单实现打开系统相册选择一张图片并显示在UI上,适用与个人主页头像的切换。 1. 添加存储权限。AndroidManifest.xml里添加读取内存的权限。 2. 布局。布局内容比较交单,一个Button用来打开相册;一个ImageView用来接收从相册选择的图片。 3. 动态申请权限。Google 在 Android  6.0

    2024年02月03日
    浏览(28)
  • Android相册选择图片、相机拍照上传功能实现(上)

    先上效果图 下面就来说一下相册选择图片和相机拍照的实现 相册选择图片很简单,只需要通过 Intent 设置拉起就可以了 Intent 拉起相册 /** 打开相册 @param type 打开类型区分码(type是我用来区分回调的) / private void openGallery(int type) { Intent gallery = new Intent(Intent.ACTION_PICK); galler

    2024年04月16日
    浏览(43)
  • Android webview上传图片(调起相册/相机上传)

    概述 默认情况 WebView 不支持input type=file,WebView 点击没有反应。 兼容 重写 webview 的 webchromeClient 中的 openFileChooser 方法。Android 版本的多样性,就理所当然的各种兼容。 具体代码实现 网上也有很多实现方式,这边记录一下自己用到的一种 webview 调用时,弹出本地弹框,选择(

    2023年04月21日
    浏览(30)
  • Android 13 骁龙相机点击拍照流程分析(二)——点击拍照到存入相册

            本篇是在Android 13 骁龙相机点击拍照流程分析(一)——点击拍照到更新到左下角缩略图文章的基础上进行延申的,前面的预览、点击拍照的过程参考第一篇:Android 13 骁龙相机点击拍照流程分析(一)——点击拍照到更新到左下角缩略图-CSDN博客         从第一篇的

    2024年02月06日
    浏览(41)
  • iOS——调用系统相册和相机

    调用相册需要用到UIImagePickerController,这是iOS系统提供的和系统的相册和相机交互的一个类,可以用来获取相册的照片,也可以调用系统的相机拍摄照片或者视频。该类的继承结构是: UIImagePickerController–UINavigationController–UIViewController–UIResponder–NSObject 首先需要导入对应的库和

    2024年02月04日
    浏览(26)
  • android相机、相册相关(android13 适配)13又又又又又又搞事,让第三方难以生存,踩坑

    前几天公司开发的新项目要上线,结果...... 由于项目中有用户更换头像功能,应用市场经过检测android13无法更换头像,也没有崩溃也没有反应,所以App就被无情退回,相当无奈,那就查问题,手头有没有android13测试机,怎么办,怎么办,怎么办...那就想办法,还好vivo有云测

    2024年02月06日
    浏览(54)
  • 安卓RecyclerView实现系统相册相机添加多个图片

    安卓RecyclerView实现系统相册相机添加多个图片 1.这个是弹出一个弹框选择相册还是相机 2.` 这里是activity的回调方法. // Bitmap roundedCornerBitmap = getRoundedCornerBitmap(bitmap, 400); 3.弹框布局 4.RecyclerView布局 5.RecyclerView布局里面的二个布局 因为要实现的是在RecyclerView里面添加一个添加按

    2024年02月20日
    浏览(32)
  • 在uniapp中从本地相册选择图片或使用相机拍照

    在uniapp中从本地相册选择图片或使用相机拍照,可以使用uniapp中内置的API uni.chooseImage 。 参数 名称 类型 必填 默认值 描述 options ChooseImageOptions 是 - - ChooseImageOptions 属性值 名称 类型 必备 默认值 描述 count number 否 9 最多可以选择的图片张数,app端不限制,微信小程序最多可

    2024年02月04日
    浏览(34)
  • 微信小程序:chooseimage从本地相册选择图片或使用相机拍照

    文档 https://uniapp.dcloud.net.cn/api/media/image.html#chooseimage https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html 代码示例

    2024年02月04日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包