Android:Kotlin实现调用相机资源拍照并显示

1先了解startActivityForResult(intent,requestCode)过期的解决方案

在需要跳转另一个界面后返回,当另一个界面进行销毁之后,希望获得界面的一些值,此时使用的方法是 startActivityForResult,但是如下所示,显示该方法已经过期了,因此下面使用推荐的registerForActivityResult
在这里插入图片描述
在这里插入图片描述使用registerForActivityResult来解决过期问题。一定要注意参数声明的位置是在Activity类内,否则就会报错。

class CameraTest:AppCompatActivity() {
    
    
    //实现回调函数,用于处理返回当前界面后的数据处理
    val  launcherCallback=ActivityResultCallback<ActivityResult>{
    
     result ->
        if(result.resultCode== Activity.RESULT_OK){
    
    
           //在此处进行返回数据之后逻辑代码的处理
        }
    }
    val intentLauncher=registerForActivityResult(ActivityResultContracts.StartActivityForResult(),launcherCallback)
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.camera_test)
        //点击按钮之后进行界面的跳转
        use_camera.setOnClickListener(){
    
    
            val intent= Intent(this,Another::class.java)
            intent.putExtra("key",value)
            //startActivityForResult(intent,1)//这个方法过期了,,需要使用下面这个方法
            intentLauncher.launch(intent)
        }
    }

2点击按钮实现调用相机且显示拍照的结果

1准备显示数据的布局xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/use_camera"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="点击拍照"/>

    <ImageView
        android:id="@+id/show_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>
    
</LinearLayout>

2处理拍照和拍照后的逻辑

package com.njupt.kotlinlearn.notificationandmedia

import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import android.net.Uri

import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import com.njupt.kotlinlearn.R
import kotlinx.android.synthetic.main.camera_test.*
import java.io.File

class CameraTest:AppCompatActivity() {
    
    

    lateinit var imageUri:Uri
    lateinit var outPutImage:File

    //实现回调函数,当相机界面被销毁之后,图片会缓存到指定的地点,然后到指定的路径中去获取图片和显示即可
    val  launcherCallback=ActivityResultCallback<ActivityResult>{
    
     result ->
        Log.d("result","${
      
      result.data}")
        if(result.resultCode== Activity.RESULT_OK){
    
    
            val bitMap=BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))
            show_image.setImageBitmap(rotateIfRequired(bitMap))
        }
    }

    val intentLauncher=registerForActivityResult(ActivityResultContracts.StartActivityForResult(),launcherCallback)

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.camera_test)


        use_camera.setOnClickListener(){
    
    
            //创建一个file对象,指明照片的存储路径是缓存的目录和为拍下的照片取名为output_image.jpg
            outPutImage=File(externalCacheDir,"output_image.jpg")
            if(outPutImage.exists()){
    
    
                outPutImage.delete()
            }
            outPutImage.createNewFile()
            //如果版本低于7,就用uri将file对象转化成uri对象,否则就封装成uri对象
            imageUri=if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
    
    
                //FileProvider是一种特殊的ContentProvider
                FileProvider.getUriForFile(this,"com.example.cameraalbumtest.fileprovider",outPutImage)
            }else{
    
    
                Uri.fromFile(outPutImage)
            }
            val intent= Intent("android.media.action.IMAGE_CAPTURE")
            //调用指定了图片输出的地址,当相机被调用的时候,指定了拍照之后的存储地址
            intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)
            //startActivityForResult(intent,1)//这个方法过期了,,需要使用下面这个方法
            intentLauncher.launch(intent)
        }
    }
//处理照片拍照的旋转问题
    private fun rotateIfRequired(bitmap:Bitmap):Bitmap{
    
    
        val exif =ExifInterface(outPutImage.path)
        val orientation=exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL)
        return when(orientation){
    
    
            ExifInterface.ORIENTATION_ROTATE_90->rotateBitmap(bitmap,90)
            ExifInterface.ORIENTATION_ROTATE_180->rotateBitmap(bitmap,180)
            ExifInterface.ORIENTATION_ROTATE_270->rotateBitmap(bitmap,270)
            else->bitmap
        }
    }
    private fun rotateBitmap(bitmap:Bitmap,degree:Int):Bitmap{
    
    
        val matrix= Matrix()
        matrix.postRotate(degree.toFloat())
        val rotatedBitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.width,bitmap.height,matrix,true)
        bitmap.recycle()
        return rotatedBitmap
    }
}

3在xml中加入程序需要的provider和数据访问路径

<provider
            android:authorities="com.example.cameraalbumtest.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/file_path"/>
        </provider>

在res目录下新建一个文件夹为xml,然后在xml文件夹下新建名为file_path的xml文件,下面选择paths,

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

点击按钮运行即可出现拍照的结果
在这里插入图片描述

3处理一个界面访问多个界面时使用registerForActivityResult的结果返回值问题

使用多个回调函数和多个launcher处理结果即可


class CameraTest:AppCompatActivity() {
    
    

    lateinit var imageUri:Uri
    lateinit var outPutImage:File

    //实现回调函数,当相机界面被销毁之后,图片会缓存到指定的地点,然后到指定的路径中去获取图片和显示即可
    val  launcherCallback=ActivityResultCallback<ActivityResult>{
    
     result ->
        if(result.resultCode== Activity.RESULT_OK){
    
    
            val bitMap=BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))
            show_image.setImageBitmap(rotateIfRequired(bitMap))
        }
    }
    //在写一个回调函数用来处理其他界面返回的请求
    val  launcherCallback2=ActivityResultCallback<ActivityResult>{
    
     result ->
         if(result.resultCode== Activity.RESULT_OK){
    
    
            //要在这里面进行
            result.data!!.data?.let{
    
     uri->
                //选择显示的图片
                val bitmap=getBitMapFromUri(uri)
                show_image.setImageBitmap(bitmap)
            }
        }
    }
    private fun getBitMapFromUri(uri: Uri)=contentResolver.openFileDescriptor(uri,"r")?.use {
    
    
        BitmapFactory.decodeFileDescriptor(it.fileDescriptor) }

    val intentLauncher=registerForActivityResult(ActivityResultContracts.StartActivityForResult(),launcherCallback)
    val intentLauncher2=registerForActivityResult(ActivityResultContracts.StartActivityForResult(),launcherCallback2)

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.camera_test)


        use_camera.setOnClickListener(){
    
    
            //创建一个file对象,指明照片的存储路径是缓存的目录和为拍下的照片取名为output_image.jpg
            outPutImage=File(externalCacheDir,"output_image.jpg")
            if(outPutImage.exists()){
    
    
                outPutImage.delete()
            }
            outPutImage.createNewFile()
            //如果版本低于7,就用uri将file对象转化成uri对象,否则就封装成uri对象
            imageUri=if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
    
    
                //FileProvider是一种特殊的ContentProvider
                FileProvider.getUriForFile(this,"com.example.cameraalbumtest.fileprovider",outPutImage)
            }else{
    
    
                Uri.fromFile(outPutImage)
            }
            val intent= Intent("android.media.action.IMAGE_CAPTURE")
            //调用指定了图片输出的地址,当相机被调用的时候,指定了拍照之后的存储地址
            intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)
            //startActivityForResult(intent,1)//这个方法过期了,,需要使用下面这个方法
            intentLauncher.launch(intent)
        }
        select_photo_from_file.setOnClickListener(){
    
    
            val intent=Intent(Intent.ACTION_OPEN_DOCUMENT)
            intent.addCategory(Intent.CATEGORY_OPENABLE)
            //显示image目录下的所有可以打开的文件
            intent.type="image/*"
            intentLauncher2.launch(intent)
        }
    }

    private fun rotateIfRequired(bitmap:Bitmap):Bitmap{
        val exif =ExifInterface(outPutImage.path)
        val orientation=exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL)
        return when(orientation){
            ExifInterface.ORIENTATION_ROTATE_90->rotateBitmap(bitmap,90)
            ExifInterface.ORIENTATION_ROTATE_180->rotateBitmap(bitmap,180)
            ExifInterface.ORIENTATION_ROTATE_270->rotateBitmap(bitmap,270)
            else->bitmap
        }
    }
    private fun rotateBitmap(bitmap:Bitmap,degree:Int):Bitmap{
        val matrix= Matrix()
        matrix.postRotate(degree.toFloat())
        val rotatedBitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.width,bitmap.height,matrix,true)
        bitmap.recycle()
        return rotatedBitmap
    }
}

猜你喜欢

转载自blog.csdn.net/m0_56184347/article/details/129628216
今日推荐