├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── laquysoft │ │ └── sounddetector │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── laquysoft │ │ │ └── sounddetector │ │ │ ├── MainActivity.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── SoundDetector.kt │ │ │ ├── ui │ │ │ └── theme │ │ │ │ ├── Color.kt │ │ │ │ ├── Shape.kt │ │ │ │ ├── Theme.kt │ │ │ │ └── Type.kt │ │ │ └── util │ │ │ └── ViewModel.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── cry.jpg │ │ ├── ic_launcher_background.xml │ │ ├── knock.jpg │ │ ├── listening.png │ │ └── notlistening.png │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── laquysoft │ └── sounddetector │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── results ├── screenshot_1.jpg ├── screenshot_2.jpg └── screenshot_3.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Mac files 6 | .DS_Store 7 | 8 | # files for the dex VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # generated files 15 | bin/ 16 | gen/ 17 | 18 | # Ignore gradle files 19 | .gradle/ 20 | build/ 21 | 22 | # Local configuration file (sdk path, etc) 23 | local.properties 24 | 25 | # Proguard folder generated by Eclipse 26 | proguard/ 27 | proguard-project.txt 28 | 29 | # Eclipse files 30 | .project 31 | .classpath 32 | .settings/ 33 | 34 | # Android Studio/IDEA 35 | *.iml 36 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SoundDetector 2 | 3 | ## :scroll: Description 4 | Sound Detection Android App Using Jetpack Compose and HMS ML Kit 5 | - [HMS ML Kit Sound Detection](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/sound-detection-0000001055282786) 6 | - [JetPack Compose](https://developer.android.com/jetpack/compose) 7 | 8 | With HMS ML Kit Sound detection you will be able to detect up to 12 different sounds: 9 | 10 | LAUGHTER, 11 | BABY_CRY, 12 | SNORING, 13 | SNEEZE, 14 | SCREAMING, 15 | MEOW, 16 | BARK, 17 | WATER, 18 | CAR_ALARM, 19 | DOORBELL, 20 | KNOCK, 21 | ALARM, 22 | STEAM_WHISTLE 23 | 24 | In this app you can check the Knocking sound and Baby crying sound detection. 25 | 26 | And the UI is developed with Jetpack Compose reacting seamlessly to the detected sound. 27 | 28 | ## :camera_flash: Screenshots 29 | 30 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | id 'com.huawei.agconnect' 5 | } 6 | 7 | android { 8 | compileSdkVersion 30 9 | buildToolsVersion "30.0.3" 10 | 11 | defaultConfig { 12 | applicationId "com.laquysoft.sounddetector" 13 | minSdkVersion 21 14 | targetSdkVersion 30 15 | versionCode 1 16 | versionName "1.0" 17 | 18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 19 | } 20 | 21 | buildTypes { 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_8 29 | targetCompatibility JavaVersion.VERSION_1_8 30 | } 31 | kotlinOptions { 32 | jvmTarget = '1.8' 33 | useIR = true 34 | } 35 | buildFeatures { 36 | compose true 37 | } 38 | composeOptions { 39 | kotlinCompilerExtensionVersion compose_version 40 | kotlinCompilerVersion '1.4.30' 41 | } 42 | } 43 | 44 | dependencies { 45 | 46 | implementation 'androidx.core:core-ktx:1.3.2' 47 | implementation 'androidx.appcompat:appcompat:1.2.0' 48 | implementation 'com.google.android.material:material:1.3.0' 49 | implementation "androidx.compose.ui:ui:$compose_version" 50 | implementation "androidx.compose.material:material:$compose_version" 51 | implementation "androidx.compose.ui:ui-tooling:$compose_version" 52 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' 53 | implementation "androidx.activity:activity-compose:1.3.0-alpha05" 54 | implementation "androidx.compose.runtime:runtime-livedata:$compose_version" 55 | implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha03' 56 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' 57 | implementation 'androidx.core:core-ktx:1.3.2' 58 | 59 | implementation 'com.huawei.hms:ml-speech-semantics-sounddect-model:2.1.0.300' 60 | implementation 'com.huawei.hms:ml-speech-semantics-sounddect-sdk:2.1.0.300' 61 | 62 | testImplementation 'junit:junit:4.+' 63 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 64 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 65 | } 66 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/laquysoft/sounddetector/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.laquysoft.sounddetector 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.laquysoft.sounddetector", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/laquysoft/sounddetector/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.laquysoft.sounddetector 2 | 3 | import android.Manifest 4 | import android.content.pm.PackageManager 5 | import android.os.Bundle 6 | import androidx.activity.ComponentActivity 7 | import androidx.activity.compose.setContent 8 | import androidx.compose.animation.AnimatedVisibility 9 | import androidx.compose.animation.ExperimentalAnimationApi 10 | import androidx.compose.foundation.Image 11 | import androidx.compose.foundation.clickable 12 | import androidx.compose.foundation.layout.* 13 | import androidx.compose.material.Card 14 | import androidx.compose.material.CircularProgressIndicator 15 | import androidx.compose.material.MaterialTheme 16 | import androidx.compose.material.Surface 17 | import androidx.compose.runtime.* 18 | import androidx.compose.runtime.livedata.observeAsState 19 | import androidx.compose.ui.Alignment 20 | import androidx.compose.ui.Modifier 21 | import androidx.compose.ui.res.painterResource 22 | import androidx.compose.ui.tooling.preview.Preview 23 | import androidx.compose.ui.unit.dp 24 | import androidx.core.app.ActivityCompat 25 | import androidx.lifecycle.viewmodel.compose.viewModel 26 | import com.laquysoft.sounddetector.ui.theme.SoundDetectorTheme 27 | import com.laquysoft.sounddetector.util.viewModelProviderFactoryOf 28 | 29 | class MainActivity : ComponentActivity() { 30 | 31 | val soundDetector = SoundDetector(this) 32 | 33 | @ExperimentalAnimationApi 34 | override fun onCreate(savedInstanceState: Bundle?) { 35 | super.onCreate(savedInstanceState) 36 | 37 | setContent { 38 | SoundDetectorTheme { 39 | 40 | val viewModel: MainViewModel = viewModel( 41 | factory = viewModelProviderFactoryOf { MainViewModel(soundDetector) } 42 | ) 43 | val state by viewModel.state.observeAsState(State()) 44 | 45 | checkMicrophonePermission() 46 | 47 | Home( 48 | state, 49 | viewModel::startListening, 50 | viewModel::stopListening 51 | ) 52 | } 53 | } 54 | } 55 | 56 | private fun checkMicrophonePermission() { 57 | if (ActivityCompat.checkSelfPermission( 58 | this, 59 | Manifest.permission.RECORD_AUDIO 60 | ) != PackageManager.PERMISSION_GRANTED 61 | ) { 62 | ActivityCompat.requestPermissions( 63 | this, arrayOf( 64 | Manifest.permission.RECORD_AUDIO 65 | ), 0x123 66 | ) 67 | } 68 | } 69 | } 70 | 71 | @ExperimentalAnimationApi 72 | @Composable 73 | fun Home(state: State, startTimer: () -> Unit = {}, stopTimer: () -> Unit = {}) { 74 | Surface( 75 | color = MaterialTheme.colors.background, 76 | modifier = Modifier 77 | .fillMaxHeight() 78 | .fillMaxWidth() 79 | ) { 80 | Box(contentAlignment = Alignment.Center) { 81 | Card { 82 | var expanded by remember { mutableStateOf(false) } 83 | 84 | Column { 85 | 86 | DetectorStatus(state, Modifier.clickable { 87 | if (state.isDetectorRunning) stopTimer() else startTimer() 88 | expanded = !expanded 89 | }) 90 | 91 | DetectionStatus(state = state, expanded = expanded) 92 | } 93 | } 94 | } 95 | } 96 | } 97 | 98 | @ExperimentalAnimationApi 99 | @Composable 100 | private fun DetectionStatus(state: State, expanded: Boolean) { 101 | AnimatedVisibility(expanded) { 102 | Spacer(Modifier.size(20.dp)) 103 | 104 | Box( 105 | contentAlignment = Alignment.Center, 106 | modifier = Modifier 107 | .size(128.dp, 128.dp) 108 | .padding(16.dp) 109 | ) { 110 | if (state.detectedSound == null) { 111 | CircularProgressIndicator(Modifier.size(64.dp, 64.dp)) 112 | } else { 113 | DetectedSound(state.detectedSound) 114 | } 115 | } 116 | } 117 | } 118 | 119 | @Composable 120 | private fun DetectorStatus(state: State, modifier: Modifier) { 121 | if (state.isDetectorRunning) { 122 | Image( 123 | painterResource(R.drawable.notlistening), 124 | contentDescription = null, 125 | modifier = modifier.size(128.dp, 128.dp) 126 | ) 127 | } else { 128 | Image( 129 | painterResource(R.drawable.listening), 130 | contentDescription = null, 131 | modifier = modifier.size(128.dp, 128.dp) 132 | ) 133 | } 134 | } 135 | 136 | @Composable 137 | fun DetectedSound(detectedSoundEvent: SoundEvent?) { 138 | when (detectedSoundEvent) { 139 | SoundEvent.KNOCK -> { 140 | Image( 141 | painterResource(R.drawable.knock), 142 | contentDescription = null 143 | ) 144 | } 145 | SoundEvent.BABY_CRY -> { 146 | Image( 147 | painterResource(R.drawable.cry), 148 | contentDescription = null 149 | ) 150 | } 151 | else -> { 152 | } 153 | } 154 | } 155 | 156 | @ExperimentalAnimationApi 157 | @Preview(showBackground = true) 158 | @Composable 159 | fun DefaultPreview() { 160 | SoundDetectorTheme { 161 | Home(state = State(isDetectorRunning = true)) 162 | } 163 | } 164 | 165 | @ExperimentalAnimationApi 166 | @Preview(showBackground = true) 167 | @Composable 168 | fun DefaultPreviewDetectorNotRunning() { 169 | SoundDetectorTheme { 170 | Home(state = State(isDetectorRunning = false)) 171 | } 172 | } 173 | 174 | @ExperimentalAnimationApi 175 | @Preview(showBackground = true) 176 | @Composable 177 | fun DefaultPreviewKnockDetected() { 178 | SoundDetectorTheme { 179 | Home(state = State(isDetectorRunning = true, detectedSound = SoundEvent.KNOCK)) 180 | } 181 | } -------------------------------------------------------------------------------- /app/src/main/java/com/laquysoft/sounddetector/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.laquysoft.sounddetector 2 | 3 | import android.os.Bundle 4 | import androidx.lifecycle.LiveData 5 | import androidx.lifecycle.MutableLiveData 6 | import androidx.lifecycle.ViewModel 7 | import com.huawei.hms.mlsdk.sounddect.MLSoundDector 8 | 9 | class MainViewModel(private val soundDetector: SoundDetector) : ViewModel() { 10 | 11 | private val _state = MutableLiveData() 12 | val state: LiveData = _state 13 | 14 | init { 15 | soundDetector.setCallbacks( 16 | onSuccess = { result -> onSoundDetected(result) }, 17 | onError = { errCode -> onDetectorError(errCode) }) 18 | } 19 | 20 | fun startListening() { 21 | soundDetector.startDetection() 22 | 23 | val currentState = _state.value 24 | if (currentState?.isDetectorRunning == true) { 25 | return 26 | } 27 | 28 | _state.value = State(isDetectorRunning = true) 29 | } 30 | 31 | fun stopListening() { 32 | soundDetector.stopDetection() 33 | 34 | _state.value = State(isDetectorRunning = false) 35 | } 36 | 37 | private fun onSoundDetected(result: Bundle) { 38 | val soundType = result.getInt(MLSoundDector.RESULTS_RECOGNIZED) 39 | if (soundType in 1..12) { 40 | _state.value = State( 41 | isDetectorRunning = true, 42 | detectedSound = SoundEvent.values()[soundType] 43 | ) 44 | } 45 | } 46 | 47 | private fun onDetectorError(errorCode: Int) { 48 | _state.value = State(isDetectorRunning = true, error = errorCode.toString()) 49 | } 50 | 51 | } 52 | 53 | data class State( 54 | val isDetectorRunning: Boolean = false, 55 | val detectedSound: SoundEvent? = null, 56 | val error: String? = null 57 | ) 58 | 59 | enum class SoundEvent { 60 | LAUGHTER, 61 | BABY_CRY, 62 | SNORING, 63 | SNEEZE, 64 | SCREAMING, 65 | MEOW, 66 | BARK, 67 | WATER, 68 | CAR_ALARM, 69 | DOORBELL, 70 | KNOCK, 71 | ALARM, 72 | STEAM_WHISTLE 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/laquysoft/sounddetector/SoundDetector.kt: -------------------------------------------------------------------------------- 1 | package com.laquysoft.sounddetector 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import com.huawei.hms.mlsdk.sounddect.MLSoundDectListener 6 | import com.huawei.hms.mlsdk.sounddect.MLSoundDector 7 | 8 | class SoundDetector(private val context: Context) { 9 | var mlSoundDetector: MLSoundDector = MLSoundDector.createSoundDector() 10 | 11 | fun startDetection() { 12 | mlSoundDetector.start(context) 13 | } 14 | 15 | fun stopDetection() { 16 | mlSoundDetector.stop() 17 | } 18 | 19 | fun setCallbacks( 20 | onSuccess: (Bundle) -> Unit = {}, 21 | onError: (Int) -> Unit = {} 22 | ) { 23 | mlSoundDetector.setSoundDectListener(object : MLSoundDectListener { 24 | override fun onSoundSuccessResult(result: Bundle) { 25 | onSuccess(result) 26 | } 27 | 28 | override fun onSoundFailResult(errCode: Int) { 29 | onError(errCode) 30 | } 31 | }) 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/com/laquysoft/sounddetector/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.laquysoft.sounddetector.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple200 = Color(0xFFBB86FC) 6 | val Purple500 = Color(0xFF6200EE) 7 | val Purple700 = Color(0xFF3700B3) 8 | val Teal200 = Color(0xFF03DAC5) -------------------------------------------------------------------------------- /app/src/main/java/com/laquysoft/sounddetector/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.laquysoft.sounddetector.ui.theme 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val Shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/laquysoft/sounddetector/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.laquysoft.sounddetector.ui.theme 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.material.MaterialTheme 5 | import androidx.compose.material.darkColors 6 | import androidx.compose.material.lightColors 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.graphics.Color 9 | 10 | private val DarkColorPalette = darkColors( 11 | primary = Purple200, 12 | primaryVariant = Purple700, 13 | secondary = Teal200, 14 | background = Color.Black 15 | ) 16 | 17 | private val LightColorPalette = lightColors( 18 | primary = Purple500, 19 | primaryVariant = Purple700, 20 | secondary = Teal200, 21 | background = Color.Gray 22 | 23 | /* Other default colors to override 24 | background = Color.White, 25 | surface = Color.White, 26 | onPrimary = Color.White, 27 | onSecondary = Color.Black, 28 | onBackground = Color.Black, 29 | onSurface = Color.Black, 30 | */ 31 | ) 32 | 33 | @Composable 34 | fun SoundDetectorTheme( 35 | darkTheme: Boolean = isSystemInDarkTheme(), 36 | content: @Composable() () -> Unit 37 | ) { 38 | val colors = if (darkTheme) { 39 | DarkColorPalette 40 | } else { 41 | LightColorPalette 42 | } 43 | 44 | MaterialTheme( 45 | colors = colors, 46 | typography = Typography, 47 | shapes = Shapes, 48 | content = content 49 | ) 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/laquysoft/sounddetector/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.laquysoft.sounddetector.ui.theme 2 | 3 | import androidx.compose.material.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | body1 = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp 15 | ) 16 | /* Other default text styles to override 17 | button = TextStyle( 18 | fontFamily = FontFamily.Default, 19 | fontWeight = FontWeight.W500, 20 | fontSize = 14.sp 21 | ), 22 | caption = TextStyle( 23 | fontFamily = FontFamily.Default, 24 | fontWeight = FontWeight.Normal, 25 | fontSize = 12.sp 26 | ) 27 | */ 28 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/laquysoft/sounddetector/util/ViewModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.laquysoft.sounddetector.util 18 | 19 | import androidx.lifecycle.ViewModel 20 | import androidx.lifecycle.ViewModelProvider 21 | 22 | /** 23 | * Returns a [ViewModelProvider.Factory] which will return the result of [create] when it's 24 | * [ViewModelProvider.Factory.create] function is called. 25 | * 26 | * If the created [ViewModel] does not match the requested class, an [IllegalArgumentException] 27 | * exception is thrown. 28 | */ 29 | fun viewModelProviderFactoryOf( 30 | create: () -> VM 31 | ): ViewModelProvider.Factory = SimpleFactory(create) 32 | 33 | /** 34 | * This needs to be a named class currently to workaround a compiler issue: b/163807311 35 | */ 36 | private class SimpleFactory( 37 | private val create: () -> VM 38 | ) : ViewModelProvider.Factory { 39 | override fun create(modelClass: Class): T { 40 | val vm = create() 41 | if (modelClass.isInstance(vm)) { 42 | @Suppress("UNCHECKED_CAST") 43 | return vm as T 44 | } 45 | throw IllegalArgumentException("Can not create ViewModel for class: $modelClass") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/drawable/cry.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/knock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/drawable/knock.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/listening.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/drawable/listening.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/notlistening.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/drawable/notlistening.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giolaq/SoundDetector/5d251139422d9ff1fc90e538b5772847f1484ce3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SoundDetector 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 21 | 22 |