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.