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
22 changes: 10 additions & 12 deletions Android/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import com.google.protobuf.gradle.id
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.google.protobuf)
}

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

compileSdk {
version = release(37)
}
defaultConfig {
applicationId = "io.github.teamclouday.AndroidMic"
minSdk = 23
targetSdk = 36
targetSdk = 37
versionCode = 24
versionName = "2.2.8"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down Expand Up @@ -72,12 +72,7 @@ android {
targetCompatibility = JavaVersion.VERSION_21
}

kotlin {
compilerOptions {
// set the target JVM bytecode
jvmTarget.set(JvmTarget.JVM_21)
}
}

buildFeatures {
prefab = true
compose = true
Expand All @@ -99,7 +94,11 @@ android {
// resources.excludes.add("google/protobuf/*.proto")
// }

sourceSets.getByName("main").resources.srcDir("src/main/proto")
sourceSets.named("main") {
resources {
directories.add(layout.projectDirectory.dir("src/main/proto").toString())
}
}
}

protobuf {
Expand Down Expand Up @@ -150,7 +149,6 @@ dependencies {

// integration test
androidTestImplementation(composeBom)
androidTestImplementation(libs.test.junit.ktx)
androidTestImplementation(libs.kotlinx.coroutines.test)
androidTestImplementation(libs.androidx.runner)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import kotlinx.coroutines.launch


private const val TAG = "AndroidMicApp"

class AndroidMicApp : Application() {


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.milliseconds


data class ServiceStates(
Expand All @@ -37,10 +38,19 @@ const val WAIT_PERIOD = 500L

const val BIND_SERVICE_ACTION = "BIND_SERVICE_ACTION"
const val STOP_STREAM_ACTION = "STOP_STREAM_ACTION"
const val MUTE_ACTION = "MUTE_ACTION"
const val UNMUTE_ACTION = "UNMUTE_ACTION"

class ForegroundService : Service() {
private val scope = CoroutineScope(Dispatchers.Default)

fun updateNotification() {
val notificationManager =
getSystemService(NotificationManager::class.java)
val notification = messageui.getNotification(states.isMuted)
notificationManager.notify(NOTIF_ID, notification)
}

private inner class ServiceHandler(looper: Looper) : Handler(looper) {
override fun handleMessage(msg: Message) {

Expand All @@ -57,11 +67,13 @@ class ForegroundService : Service() {
Command.Mute -> {
states.isMuted = true
managerAudio?.mute()
updateNotification()
}

Command.Unmute -> {
states.isMuted = false
managerAudio?.unmute()
updateNotification()
}
}

Expand Down Expand Up @@ -136,6 +148,20 @@ class ForegroundService : Service() {
serviceShouldStop = false
}

MUTE_ACTION -> {
states.isMuted = true
managerAudio?.mute()
updateNotification()
reply(uiMessenger, ResponseData(isMuted = true))
}

UNMUTE_ACTION -> {
states.isMuted = false
managerAudio?.unmute()
updateNotification()
reply(uiMessenger, ResponseData(isMuted = false))
}

else -> {
Log.w(TAG, "unknown action for onStartCommand")
}
Expand All @@ -154,7 +180,7 @@ class ForegroundService : Service() {
// (Service is not destroy when the screen rotate)
serviceShouldStop = true
scope.launch {
delay(3000L)
delay(3000.milliseconds)
if (serviceShouldStop)
stopService()
}
Expand Down Expand Up @@ -325,11 +351,10 @@ class ForegroundService : Service() {

managerAudio?.start()

// the id is not important here
// we need to start in foreground to use the mic
// but no need to specified a flag because we declared
// but no need to specify a flag because we declared
// the type in manifest
startForeground(3, messageui.getNotification())
startForeground(NOTIF_ID, messageui.getNotification(states.isMuted))

Log.d(TAG, "startAudio [recording]")
states.isAudioStarted = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import kotlinx.coroutines.launch

const val CHANNEL_ID = "Service"

const val NOTIF_ID = 3

class MessageUi(private val ctx: ForegroundService) {
// show message on UI
fun showMessage(message: String) {
Expand All @@ -23,7 +25,7 @@ class MessageUi(private val ctx: ForegroundService) {
}


fun getNotification(): Notification {
fun getNotification(isMuted: Boolean): Notification {
// launch activity
val launchIntent = Intent(ctx, MainActivity::class.java).apply {
flags =
Expand All @@ -33,11 +35,14 @@ class MessageUi(private val ctx: ForegroundService) {
PendingIntent.getActivity(ctx, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE)


val stopStreamingIntent: Intent = Intent(ctx, ForegroundService::class.java)
.setAction(STOP_STREAM_ACTION)

val pStopStreamingIntent = PendingIntent.getService(
ctx, 0, stopStreamingIntent, PendingIntent.FLAG_IMMUTABLE
ctx, 0, Intent(ctx, ForegroundService::class.java)
.setAction(STOP_STREAM_ACTION), PendingIntent.FLAG_IMMUTABLE
)

val pMuteIntent = PendingIntent.getService(
ctx, 0, Intent(ctx, ForegroundService::class.java)
.setAction(if (isMuted) UNMUTE_ACTION else MUTE_ACTION ), PendingIntent.FLAG_IMMUTABLE
)

val builder = NotificationCompat.Builder(ctx, CHANNEL_ID)
Expand All @@ -54,6 +59,13 @@ class MessageUi(private val ctx: ForegroundService) {
pStopStreamingIntent
)
)
.addAction(
NotificationCompat.Action(
R.drawable.ic_launcher_foreground,
ctx.getString(if (isMuted) R.string.unmute else R.string.mute),
pMuteIntent
)
)

return builder.build()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ private const val TAG: String = "UDP streamer"
class UdpStreamer(private val scope: CoroutineScope, val ip: String, var port: Int) : Streamer {



private val socket: DatagramSocket = DatagramSocket()
private val address = InetAddress.getByName(ip)
private var streamJob: Job? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import io.github.teamclouday.androidMic.ui.utils.rememberWindowInfo
import io.github.teamclouday.androidMic.utils.ignore

private const val TAG = "MainActivity"

class MainActivity : ComponentActivity() {

val vm: MainViewModel by viewModels()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

private const val TAG = "MainViewModel"

class MainViewModel : ViewModel() {

val prefs: AppPreferences = AndroidMicApp.appModule.appPreferences
Expand Down Expand Up @@ -189,7 +190,6 @@ class MainViewModel : ViewModel() {
}



fun setTheme(theme: Themes) {
viewModelScope.launch {
prefs.theme.update(theme)
Expand Down
Loading
Loading