BroadcastReceiver文件
class CallReceiver : BroadcastReceiver() {
private var mediaRecorder : MediaRecorder? = null
override fun onReceive(context: Context?, intent: Intent?) {
val state : String
if(intent?.action.equals("android.intent.action.PHONE_STATE")){
if(intent?.extras != null){
state = intent.getStringExtra(TelephonyManager.EXTRA_STATE).toString()
when(state){
TelephonyManager.EXTRA_STATE_RINGING -> {
Log.d("CallRec", "Ringing......")
}
TelephonyManager.EXTRA_STATE_OFFHOOK -> {
startRecording(context)
}
TelephonyManager.EXTRA_STATE_IDLE ->{
stopRecording()
}
}
}
}
}
private fun startRecording(context: Context?) {
if(context != null){
mediaRecorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) MediaRecorder(context) else MediaRecorder()
}
mediaRecorder?.apply {
setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION)
setOutputFormat(MediaRecorder.OutputFormat.AMR_NB)
setOutputFile(getRecordingFilePath())
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
}
try {
mediaRecorder?.prepare()
mediaRecorder?.start()
}
catch (e : IOException){
Log.d("CallError", e.toString())
}
Log.d("CallRec", "Call Recording Start......")
}
private fun stopRecording(){
try {
mediaRecorder?.stop()
mediaRecorder?.release()
}
catch (e : Exception){
Log.d("CallError", e.toString())
}
mediaRecorder = null
Log.d("CallRec", "Call Recording Stopped......")
}
private fun getRecordingFilePath(): String {
val directory = File(Environment.getExternalStorageDirectory(), "TestRecording")
if(!directory.exists()){
directory.mkdir()
}
val filePath = File(directory, "testing_${System.currentTimeMillis()}" + ".amr")
return filePath.path
}
}主活动类
class MainActivity : AppCompatActivity() {
private var callReceiver = CallReceiver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
allowPermission()
val makeCall: Button = findViewById(R.id.makeCall)
makeCall.setOnClickListener {
val intent = Intent(Intent.ACTION_DIAL)
startActivity(intent)
}
if(hasPermission()) {
val intentFilter = IntentFilter()
intentFilter.addAction("android.intent.action.PHONE_STATE")
this.registerReceiver(callReceiver, intentFilter)
}
else{
allowPermission()
}
}
override fun onDestroy() {
super.onDestroy()
this.unregisterReceiver(callReceiver)
}
private fun allowPermission() {
ActivityCompat.requestPermissions(
this, arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.RECORD_AUDIO
), 2
)
}
private fun hasPermission() : Boolean{
val phoneStatePermission = Manifest.permission.READ_PHONE_STATE
val writeFilePermission = Manifest.permission.WRITE_EXTERNAL_STORAGE
val recordAudioPermission = Manifest.permission.RECORD_AUDIO
return ContextCompat.checkSelfPermission(this, phoneStatePermission) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, writeFilePermission) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, recordAudioPermission) == PackageManager.PERMISSION_GRANTED
}
}
清单文件
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.CallRecording"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
LogCat
java.io.FileNotFoundException: /storage/emulated/0/TestRecording/testing_1694590203887.amr: open failed: ENOENT (No such file or directory)
我正在构建一个通话录音应用程序,我想在自定义目录中存储录制的音频文件。当我在android 8上运行这个应用程序时,它工作得很好。但是对于Android 13,它给出了EPERM(不允许操作)例外。我认为这个问题与许可有关。
2条答案
按热度按时间vx6bjr1n1#
谷歌限制通话录音功能,只有系统应用程序。在Android 8以上无法使用。[https://support.google.com/googleplay/android-developer/answer/9888170]
ghhkc1vu2#
在Android 13设备上,您不应该请求通常的WRITE权限,因为默认情况下您拥有该权限。
但您不能在外部存储的根目录中创建文件夹“TestRecording”。
相反,在已经存在的公共目录之一中创建文件夹,如下载,文档,DCIM,图片,视频。