java - 我的电话录音机服务不断崩溃

标签 java android kotlin

我的应用程序中有以下代码用于通话录音,但一旦调用“服务”,它就会崩溃!

用于检测调用并启动 AudioServiceBroadcastReceiver 是:

class PhoneStateReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {

        val state = intent.getStringExtra(TelephonyManager.EXTRA_STATE)
        val incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)

        when(state){
            TelephonyManager.EXTRA_STATE_RINGING -> {
                            Toast.makeText(context, "Ringing $incomingNumber", Toast.LENGTH_LONG).show()
                            }
            TelephonyManager.EXTRA_STATE_OFFHOOK -> {
                            Toast.makeText(context, "On Call $incomingNumber", Toast.LENGTH_LONG).show()
                            context.startService(Intent(context, AudioService::class.java))
                            }
            TelephonyManager.EXTRA_STATE_IDLE -> {
                        Toast.makeText(context, "IDLE", Toast.LENGTH_LONG).show()
                        context.stopService(Intent(context, AudioService::class.java))
                         }
        }
    }
}

用于通话录音的AudioService,但是老是崩溃:

class AudioService : Service(), MediaRecorder.OnInfoListener {

    lateinit var context: Context
    private var mRecorder: MediaRecorder? = null
    //setting maximum file size to be recorded
    private val Audio_MAX_FILE_SIZE: Long = 1000000//1Mb

    private var mOutputFile: File? = null
    private var mStartTime: Long = 0

    private val outputFile: File
        get() {
            val dateFormat = SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US)
            return File(context.filesDir, //Environment.getExternalStorageDirectory(Environment.DIRECTORY_DOWNLOADS)
                  //  .absolutePath.toString()
                    "RECORDING_"  // "/Voice Recorder/RECORDING_"
                    + dateFormat.format(Date())
                    + ".m4a")
        }

    override fun onInfo(mr: MediaRecorder?, what: Int, extra: Int) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
            stopRecording(true)
        }
    }

    override fun onBind(intent: Intent?): IBinder? {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        return null
    }

    override fun onCreate() {
        context = this
      //  Toast.makeText(context,"created", Toast.LENGTH_LONG).show()
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        Toast.makeText(context,"started recording", Toast.LENGTH_LONG).show()

        mRecorder = MediaRecorder()
        mRecorder!!.setOnInfoListener(this)

        mRecorder!!.apply {
            setAudioSource(MediaRecorder.AudioSource.MIC)
            setMaxFileSize(Audio_MAX_FILE_SIZE)
            setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)

            setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC)
            setAudioEncodingBitRate(48000)

            setAudioSamplingRate(16000)
        }
        mOutputFile = outputFile
        mOutputFile!!.parentFile.mkdirs()
        mRecorder!!.setOutputFile(mOutputFile!!.absolutePath)

        try {
            mRecorder!!.apply {
                prepare()
                start()
            }

            mStartTime = SystemClock.elapsedRealtime()
        } catch (e: IOException) {
        }

        return Service.START_STICKY
    }

    private fun stopRecording(saveFile: Boolean) {
        Toast.makeText(context,"stopped recording ", Toast.LENGTH_LONG).show()
        mRecorder!!.apply {
            stop()
            release()
        }
        mRecorder = null
        mStartTime = 0
        if (!saveFile && mOutputFile != null) {
            mOutputFile!!.delete()
        }
        // to stop the service by itself
        stopSelf()

    }

    override fun onDestroy() {
        super.onDestroy()
        stopRecording(true)
    }
}

AndroidManifest 中,我添加了如下两个:

    <receiver android:name=".broadcasts.PhoneStateReceiver">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
            <action android:name="android.intent.action.READ_PHONE_STATE" />
        </intent-filter>
    </receiver>

    <service android:name=".Services.AudioService" />

我已经在 MainActivity 中授予了 android.Manifest.permission.READ_PHONE_STATE 所需的运行时权限

更新

我在调试器中遇到了这个错误:

java.lang.RuntimeException: setAudioSource failed

因此,引用 this我添加了 Manifest.permission.RECORD_AUDIO 的运行时权限,但现在出现另一个错误,即:

java.lang.RuntimeException: start failed.

最佳答案

需要添加以下权限:

使用权限 android:name="android.permission.RECORD_AUDIO"

此外,这是一个“危险的”权限,因此必须由用户直接授予: https://developer.android.com/training/permissions/requesting

关于java - 我的电话录音机服务不断崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50121235/

相关文章:

java - JUnit 测试中的注释数量不正确

Android AudioRecorder 断言失败 : !(stepCount <= mUnreleased && mUnreleased <= mFrameCount)

android - 如何使用 Lollipop MR1 多 SIM 卡支持(通过 SubscriptionManager)获取所有 SIM 卡的 IMEI?

kotlin - 参数数量未知的 Lambda 类型

java - 如何确定 SOLR 索引的字段类型?

java - Java if 语句中的 if

java - 从手机流式传输视频

android - Overflow-x : scroll ! 重要的是不能在 Samsung Internet 上使用已翻译的 SVG

java - Kotlin - kotlin 列表过滤器是否会创建一个新的列表对象?

android - Kotlin 和 Firebase 读写数据