Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ plugins {
}

android {
namespace = "io.github.teamclouday.AndroidMic"
namespace = "io.github.teamclouday.androidMic"
compileSdk = 36

defaultConfig {
Expand Down
6 changes: 3 additions & 3 deletions Android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<uses-permission android:name="android.permission.USB_PERMISSION" />

<application
android:name="io.github.teamclouday.AndroidMic.AndroidMicApp"
android:name="io.github.teamclouday.androidMic.AndroidMicApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand All @@ -26,7 +26,7 @@
android:theme="@style/Theme.AndroidMic">

<activity
android:name="io.github.teamclouday.AndroidMic.ui.MainActivity"
android:name="io.github.teamclouday.androidMic.ui.MainActivity"
android:exported="true"
android:theme="@style/Theme.AndroidMic">
<intent-filter>
Expand All @@ -46,7 +46,7 @@
</activity>

<service
android:name="io.github.teamclouday.AndroidMic.domain.service.ForegroundService"
android:name="io.github.teamclouday.androidMic.domain.service.ForegroundService"
android:foregroundServiceType="microphone" />

</application>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.github.teamclouday.AndroidMic
package io.github.teamclouday.androidMic

import android.app.Application
import android.content.ComponentName
Expand All @@ -7,15 +7,15 @@ import android.content.ServiceConnection
import android.os.IBinder
import android.os.Messenger
import android.util.Log
import io.github.teamclouday.AndroidMic.domain.service.BIND_SERVICE_ACTION
import io.github.teamclouday.AndroidMic.domain.service.ForegroundService
import io.github.teamclouday.AndroidMic.ui.MainActivity
import io.github.teamclouday.androidMic.domain.service.BIND_SERVICE_ACTION
import io.github.teamclouday.androidMic.domain.service.ForegroundService
import io.github.teamclouday.androidMic.ui.MainActivity
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch


private const val TAG = "AndroidMicApp"
class AndroidMicApp : Application() {
private val TAG = "AndroidMicApp"


companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.github.teamclouday.AndroidMic
package io.github.teamclouday.androidMic

import android.content.Context
import io.github.teamclouday.AndroidMic.ui.utils.UiHelper
import io.github.teamclouday.androidMic.ui.utils.UiHelper


interface AppModule {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package io.github.teamclouday.AndroidMic
package io.github.teamclouday.androidMic

import android.content.Context
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import io.github.teamclouday.AndroidMic.utils.PreferencesManager
import io.github.teamclouday.androidMic.ui.utils.UiHelper
import io.github.teamclouday.androidMic.utils.PreferencesManager

object DefaultStates {
const val IP = "192.168."
Expand Down Expand Up @@ -92,4 +93,11 @@ enum class ChannelCount(val value: Int) {
Stereo -> stringResource(R.string.stereo)
}
}

fun getString(uiHelper: UiHelper): String {
return when (this) {
Mono -> uiHelper.getString(R.string.mono)
Stereo -> uiHelper.getString(R.string.stereo)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.github.teamclouday.AndroidMic.domain.audio
package io.github.teamclouday.androidMic.domain.audio

import android.Manifest
import android.content.Context
Expand All @@ -8,7 +8,7 @@ import android.media.AudioRecord
import android.media.MediaRecorder
import android.util.Log
import androidx.core.content.ContextCompat
import io.github.teamclouday.AndroidMic.domain.service.AudioPacket
import io.github.teamclouday.androidMic.domain.service.AudioPacket
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.awaitClose
Expand All @@ -19,6 +19,9 @@ import kotlinx.coroutines.launch
import java.nio.ByteBuffer
import java.nio.ByteOrder


private const val TAG: String = "MicAM"

// manage microphone recording
class MicAudioManager(
ctx: Context,
Expand All @@ -28,7 +31,6 @@ class MicAudioManager(
val channelCount: Int

) {
private val TAG: String = "MicAM"

companion object {
const val RECORD_DELAY_MS = 100L
Expand All @@ -41,6 +43,8 @@ class MicAudioManager(
private val bufferFloatConvert: ByteBuffer
private var streamJob: Job? = null

private var isMuted = false

init {
// check microphone
require(ctx.packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
Expand Down Expand Up @@ -92,6 +96,12 @@ class MicAudioManager(
// launch in scope so infinite loop will be canceled when scope exits
streamJob = scope.launch {
while (true) {

if (isMuted) {
delay(RECORD_DELAY_MS)
continue
}

if (recorder.state != AudioRecord.STATE_INITIALIZED || recorder.recordingState != AudioRecord.RECORDSTATE_RECORDING) {
delay(RECORD_DELAY_MS)
continue
Expand Down Expand Up @@ -143,6 +153,14 @@ class MicAudioManager(
}
}

fun mute() {
isMuted = true
}

fun unmute() {
isMuted = false
}

// start recording
fun start() {
recorder.startRecording()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
package io.github.teamclouday.AndroidMic.domain.service
package io.github.teamclouday.androidMic.domain.service

import android.os.Bundle
import android.os.Message
import io.github.teamclouday.AndroidMic.AppPreferences
import io.github.teamclouday.AndroidMic.AudioFormat
import io.github.teamclouday.AndroidMic.ChannelCount
import io.github.teamclouday.AndroidMic.Dialogs
import io.github.teamclouday.AndroidMic.Mode
import io.github.teamclouday.AndroidMic.SampleRates
import io.github.teamclouday.AndroidMic.utils.Either
import io.github.teamclouday.AndroidMic.utils.checkIp
import io.github.teamclouday.AndroidMic.utils.checkPort

import io.github.teamclouday.androidMic.AppPreferences
import io.github.teamclouday.androidMic.AudioFormat
import io.github.teamclouday.androidMic.ChannelCount
import io.github.teamclouday.androidMic.Dialogs
import io.github.teamclouday.androidMic.Mode
import io.github.teamclouday.androidMic.SampleRates
import io.github.teamclouday.androidMic.utils.Either
import io.github.teamclouday.androidMic.utils.checkIp
import io.github.teamclouday.androidMic.utils.checkPort

/**
* Service -> UI
*/
private const val ID_MSG: String = "ID_MSG"
private const val ID_STATE: String = "ID_STATE"
private const val ID_CONNECTION_STATE: String = "ID_CONNECTION_STATE"
private const val ID_MUTE_STATE: String = "ID_MUTE_STATE"

/**
* UI -> Service
*/
private const val ID_MODE: String = "ID_MODE"

private const val ID_IP: String = "ID_IP"
Expand All @@ -27,7 +33,7 @@ private const val ID_AUDIO_FORMAT: String = "ID_AUDIO_FORMAT"


/**
* Commands UI -> Service
* UI -> Service
*/
enum class Command {
StartStream,
Expand All @@ -36,18 +42,12 @@ enum class Command {

// called when the ui is bind
BindCheck,
}

fun Bundle.getOrdinal(key: String): Int? {
val v = this.getInt(key, Int.MIN_VALUE);

return if (v == Int.MIN_VALUE) {
null
} else {
v
}
Mute,
Unmute,
}


data class CommandData(
val command: Command,
val mode: Mode? = null,
Expand Down Expand Up @@ -134,29 +134,38 @@ data class CommandData(


/**
* Response Service -> UI
* Service -> UI
*/
enum class Response {
enum class ResponseKind {
Standard,
}

enum class ServiceState {
private enum class ConnectionState {
Connected,
Disconnected,
Disconnected;
}

private enum class MuteState {
Muted,
Unmuted,
}

data class ResponseData(
val state: ServiceState? = null,
val msg: String? = null,
val kind: Response = Response.Standard,
val isConnected: Boolean? = null,
val isMuted: Boolean? = null,
val kind: ResponseKind = ResponseKind.Standard,
) {


companion object {
fun fromMessage(msg: Message): ResponseData {
return ResponseData(
kind = Response.entries[msg.what],
state = msg.data.getOrdinal(ID_STATE)?.let { ServiceState.entries[it] },
kind = ResponseKind.entries[msg.what],
isConnected = msg.data.getOrdinal(ID_CONNECTION_STATE)
?.let { ConnectionState.entries[it] == ConnectionState.Connected },
isMuted = msg.data.getOrdinal(ID_MUTE_STATE)
?.let { MuteState.entries[it] == MuteState.Muted },
msg = msg.data.getString(ID_MSG)
)
}
Expand All @@ -168,7 +177,18 @@ data class ResponseData(
val r = Bundle()

this.msg?.let { r.putString(ID_MSG, it) }
this.state?.let { r.putInt(ID_STATE, it.ordinal) }
this.isConnected?.let {
r.putInt(
ID_CONNECTION_STATE,
(if (it) ConnectionState.Connected else ConnectionState.Disconnected).ordinal
)
}
this.isMuted?.let {
r.putInt(
ID_MUTE_STATE,
(if (it) MuteState.Muted else MuteState.Unmuted).ordinal
)
}

val reply = Message.obtain()
reply.data = r
Expand All @@ -180,4 +200,12 @@ data class ResponseData(
}


fun Bundle.getOrdinal(key: String): Int? {
val v = this.getInt(key, Int.MIN_VALUE)

return if (v == Int.MIN_VALUE) {
null
} else {
v
}
}
Loading