Bootstrap

Android一次完美的跨进程服务共享实践,大专生出身

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 = 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”)

notifyCallBack {

it.onException(result, willStartRecorderResult)

}

} else {

currentWeight = recorderConfig.weight

notifyCallBack {

it.onStart(willStartRecorderResult)

}

currentRecorderResult = willStartRecorderResult

}

}

private fun isRecording(): Boolean {

return iRecorder?.isRecording ?: false

}

@Synchronized

private fun stopRecordingInternal() {

logD(“stopRecordingInternal”)

iRecorder?.stopRecording()

currentWeight = -1

iRecorder = null

MediaScannerConnection.scanFile(

this,

arrayOf(currentRecorderResult.recorderFile?.absolutePath),

null,

null

)

notifyCallBack {

it.onStop(currentRecorderResult)

}

}

private fun notifyCallBack(done: (IRecorderCallBack) -> Unit) {

val size = remoteCallbackList.beginBroadcast()

logD(“recorded notifyCallBack size $size”)

(0 until size).forEach {

done(remoteCallbackList.getBroadcastItem(it))

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

如何做好面试突击,规划学习方向?

面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。

学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。

同时我还搜集整理2020年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节

image

在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。

image

点击:《Android架构视频+BAT面试专题PDF+学习笔记》即可免费获取~

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。

学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。

同时我还搜集整理2020年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节

[外链图片转存中…(img-rml1aLqg-1711139828171)]

在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。

[外链图片转存中…(img-Ep0la9gH-1711139828172)]

点击:《Android架构视频+BAT面试专题PDF+学习笔记》即可免费获取~

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

;