Android: Kotlin realiza chamada de recursos da câmera para tirar fotos e exibi-las

1 Primeiro entenda a solução para a expiração de startActivityForResult(intent, requestCode)

Retorne após pular para outra interface. Quando a outra interface for destruída, você deseja obter alguns valores da interface. O método usado neste momento é startActivityForResult, mas conforme mostrado abaixo, mostra que o método expirou, então use o recomendado abaixo registerForActivityResult
insira a descrição da imagem aqui
insira a descrição da imagem aquiUse registerForActivityResult para resolver problemas de expiração. Certifique-se de observar que a posição da declaração do parâmetro está dentro da classe Activity, caso contrário, um erro será relatado.

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 Clique no botão para chamar a câmera e exibir o resultado das fotos

1 Prepare o layout xml para exibição de dados

<?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 Processe a lógica de tirar fotos e tirar fotos

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 Adicione o provedor e o caminho de acesso aos dados exigidos pelo programa em xml

<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>

Crie uma nova pasta chamada xml no diretório res e, em seguida, crie um novo arquivo xml chamado file_path na pasta xml, selecione os caminhos abaixo,

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

Clique no botão para executar e o resultado da captura de fotos aparecerá
insira a descrição da imagem aqui

3 Lide com o problema de usar o valor de retorno do resultado de registerForActivityResult quando uma interface acessa várias interfaces

Use várias funções de retorno de chamada e vários lançadores para processar os resultados


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
    }
}

Acho que você gosta

Origin blog.csdn.net/m0_56184347/article/details/129628216
Recomendado
Clasificación