写点什么

Android 一次完美的跨进程服务共享实践,android 图书管理系统源码

用户头像
Android架构
关注
发布于: 刚刚

class JLMediaRecorder : IRecorder {


private var mMediaRecorder: MediaRecorder? = null


private var mState = RecorderState.IDLE


@Synchronized


override fun startRecording(recorderConfig: RecorderConfig): String {


try {


mMediaRecorder = MediaRecorder()


mMediaRecorder?.setAudioSource(recorderConfig.audioSource)


when (recorderConfig.recorderOutFormat) {


RecorderOutFormat.MPEG_4 -> {


mMediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)


mMediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)


}


RecorderOutFormat.AMR_WB -> {


mMediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.AMR_WB)


mMediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB)


}


else -> {


mMediaRecorder?.reset()


mMediaRecorder?.release()


mMediaRecorder = null


return "MediaRecorder 不支持 AudioFormat.PCM"


}


}


} catch (e: IllegalStateException) {


mMediaRecorder?.reset()


mMediaRecorder?.release()


mMediaRecorder = null


return "Error initializing media recorder 初始化失败";


}


return try {


val file = recorderConfig.recorderFile


file.parentFile.mkdirs()


file.createNewFile()


val outputPath: String = file.absolutePath


mMediaRecorder?.setOutputFile(outputPath)


mMediaRecorder?.prepare()


mMediaRecorder?.start()


mState = RecorderState.RECORDING


""


} catch (e: Exception) {


mMediaRecorder?.reset()


mMediaRecorder?.release()


mMediaRecorder = null


recorderConfig.recorderFile.delete()


e.toString()


}


}


override fun isRecording(): Boolean {


return mState == RecorderState.RECORDING


}


@Synchronized


override fun stopRecording() {


try {


if (mState == RecorderState.RECORDING) {


mMediaRecorder?.stop()


mMediaRecorder?.reset()


mMediaRecorder?.release()


}


} catch (e: java.lang.IllegalStateException) {


e.printStackTrace()


}


mMediaRecorder = null


mState = RecorderState.IDLE


}


override fun state(): RecorderState {


return mState


}


}


这里需要注意的就是加?@Synchronized因为多进程同时调用的时候会出现状态错乱问题,需要加上才安全。

AIDL 接口定义

interface IRecorderService {


void startRecording(in RecorderConfig recorderConfig);


void stopRecording(in RecorderConfig recorderConfig);


boolean isRecording(in RecorderConfig recorderConfig);


RecorderResult getActiveRecording();


void registerCallback(IRecorderCallBack callBack);


void unregisterCallback(IRecorderCallBack callBack);


}


注意点:


  • 自定义参数需要实现 Parcelable 接口

  • 需要回调的话也是 AIDL 接口定义

AIDL 接口回调定义

interface IRecorderCallBack {


void onStart(in RecorderResult result);


void onStop(in RecorderResult result);


void onException(String error,in RecorderResult result);


}

RecorderService 实现

接下来就是功能的核心,跨进程的服务


class RecorderService : Service() {


private var iRecorder: IRecorder? = null


private var currentRecorderResult: RecorderResult = RecorderResult()


private var currentWeight: Int = -1


private val remoteCallbackList: RemoteCallbackList<IRecorderCallBack> = RemoteCallbackList()


private val mBinder: IRecorderService.Stub = object : IRecorderService.Stub() {


override fun startRecording(recorderConfig: RecorderConfig) {


startRecordingInternal(recorderConfig)


}


override fun stopRecording(recorderConfig: RecorderConfig) {


if (recorderConfig.recorderId == currentRecorderResult.recorderId)


stopRecordingInternal()


else {


notifyCallBack {


it.onException(


"Cannot stop the current recording because the recorderId is not the same as the current recording",


currentRecorderResult


)


}


}


}


override fun getActiveRecording(): RecorderResult? {


return currentRecorderResult


}


override fun isRecording(recorderConfig: RecorderConfig?): Boolean {


return if (recorderConfig?.recorderId == currentRecorderResult.recorderId)


iRecorder?.isRecording ?: false


else false


}


override fun registerCallback(callBack: IRecorderCallBack) {


remoteCallbackList.register(callBack)


}


override fun unregisterCallback(callBack: IRecorderCallBack) {


remoteCallbackList.unregister(callBack)


}


}


override fun onBind(intent: Intent?): IBinder? {


return mBinder


}


@Synchronized


private fun startRecordingInternal(recorderConfig: RecorderConfig) {


val willStartRecorderResult =


RecorderResultBuilder.aRecorderResult().withRecorderFile(recorderConfig.recorderFile)


.withRecorderId(recorderConfig.recorderId).build()


if (ContextCompat.checkSelfPermission(


this@RecorderService,


android.Manifest.permission.RECORD_AUDIO


)


!= PackageManager.PERMISSION_GRANTED


) {


logD("Record audio permission not granted, can't record")


notifyCallBack {


it.onException(


"Record audio permission not granted, can't record",


willStartRecorderResult


)


}


return


}


if (ContextCompat.checkSelfPermission(


this@RecorderService,


android.Manifest.permission.WRITE_EXTERNAL_STORAGE


)


!= PackageManager.PERMISSION_GRANTED


) {


logD("External storage permission not granted, can't save recorded")


notifyCallBack {


it.onException(


"External storage permission not granted, can't save recorded",


willStartRecorderResult


)


}


return


}


if (isRecording()) {


val weight = recorderConfig.weight


if (weight < currentWeight) {


logD("Recording with weight greater than in recording")


notifyCallBack {


it.onException(


"Recording with weight greater than in recording",


willStartRecorderResult


)


}


return


}


if (weight > currentWeight) {


//只要权重大于当前权重,立即停止当前。


stopRecordingInternal()


}


if (weight == currentWeight) {


if (recorderConfig.recorderId == currentRecorderResult.recorderId) {


notifyCallBack {


it.onException(


"The same recording cannot be started repeatedly",


willStartRecorderResult


)


}


return


} else {


stopRecordingInternal()


}


}


startRecorder(recorderConfig, willStartRecorderResult)


} else {


startRecorder(recorderConfig, willStartRecorderResult)


}


}


private fun startRecorder(


recorderConfig: RecorderConfig,


willStartRecorderResult: RecorderResult


) {


logD("startRecording result ${willStartRecorderResult.toString()}")


iRecorder = when (recorderConfig.recorderOutFormat) {


RecorderOutFormat.MPEG_4, RecorderOutFormat.AMR_WB -> {


JLMediaRecorder()


}


RecorderOutFormat.PCM -> {


JLAudioRecorder()


}


}


val result = iRecorder?.startRecording(recorderConfig)


if (!result.isNullOrEmpty()) {


logD("startRecording result $result")


notify


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


CallBack {


it.onException(result, willStartRecorderResult)


}


} else {

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android一次完美的跨进程服务共享实践,android图书管理系统源码