简体   繁体   中英

How to record audio with android 11

I am making an app to record audio on an android 11 device. However, after struggling for days, I still have trouble in setting up the permission. I kept getting errors like this

I/System.out: java.io.FileNotFoundException: /storage/emulated/0/Recordings/2022-12-14T10:11:37.089test.3gp: open failed: EPERM (Operation not permitted)

And then the APP will shut down after calling recorder.start(). It looks like it needs more permission to do this. Here is my code now:

package com.example.eslab_final_impromptu

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.media.MediaRecorder
import android.media.SoundPool
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.example.eslab_final_impromptu.databinding.FragmentDetailBinding
import java.io.IOException
import java.time.LocalDateTime


class DetailFragment : Fragment() {
    private var _binding: FragmentDetailBinding? = null
    private val binding get() = _binding!!
    private var recorder: MediaRecorder? = null
    private var recording=false
    private var isRecordable=true
    private val requestPermission =
        registerForActivityResult(ActivityResultContracts.RequestPermission())
            { isGranted: Boolean ->
                if (isGranted) {

                    // Permission is granted. Continue the action or workflow in your
                    // app.
                } else {
                    isRecordable=false
                    Log.d("ddddd","permission")
                    // Explain to the user that the feature is unavailable because the
                    // feature requires a permission that the user has denied. At the
                    // same time, respect the user's decision. Don't link to system
                    // settings in an effort to convince the user to change their
                    // decision.
                }
            }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

    }
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentDetailBinding.inflate(inflater, container, false)

        if (ContextCompat.checkSelfPermission(
                requireContext(),
                Manifest.permission.RECORD_AUDIO )!= PackageManager.PERMISSION_GRANTED
        ) {
            Log.d("ddddd","audio")
            requestPermission.launch(Manifest.permission.RECORD_AUDIO)
        }
        if (ContextCompat.checkSelfPermission(
                requireContext(),
                Manifest.permission.WRITE_EXTERNAL_STORAGE )!= PackageManager.PERMISSION_GRANTED
        ) {
            Log.d("ddddd","write")
            requestPermission.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.sheet.setOnClickListener {
            val action =
                DetailFragmentDirections.actionDetailFragmentToSheetFragment()
            this.findNavController().navigate(action)
        }
        binding.settings.setOnClickListener {
        }
        binding.disconnect.setOnClickListener {
            val action =
                DetailFragmentDirections.actionDetailFragmentToHomeFragment()
            this.findNavController().navigate(action)
        }
        binding.record.setOnClickListener{
            if(!recording)
                record()
            else
                stopRecord()
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
    }
    fun record(){
        Log.d("ddddd",LocalDateTime.now().toString())
        if(!isRecordable)
            return

        var mFileName:String = Environment.getExternalStorageDirectory().absolutePath+"/Recordings/"+ LocalDateTime.now().toString()+"test.3gp"
        println(Environment.getExternalStorageState())
        recorder = MediaRecorder().apply {
            setAudioSource( MediaRecorder.AudioSource.DEFAULT)
            setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
            setOutputFile(mFileName)
            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
            try {
                prepare()
            } catch (e: IOException) {
                println(e)
            }
            start()
        }
        recording=true
    }
    fun stopRecord(){
        recorder?.apply {
            stop()
            release()
        }
        recorder = null
        recording=false
    }
}

I now request for RECORD_AUDIO and WRITE_EXTERNAL_STORAGE. Do I have to request for anything else? My device is Android 11 with SDK30.

Google release the new storage updates regarding write the file in app specific storage. You can't not access the WRITE_EXTERNAL_STORAGE permission in SDK 30 or above. Read this:https://developer.android.com/about/versions/11/privacy/storage

Remove the WRITE_EXTERNAL_STORAGE permission request.

Try this below solutions:

var mFileName:String = getContext().externalMediaDirs[0].absolutePath+"/" + System.currentTimeMillis()+"test.3gp"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM