├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── gradle.xml ├── kotlinc.xml └── misc.xml ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── hgm │ │ └── appsearch │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── hgm │ │ │ └── appsearch │ │ │ ├── MainActivity.kt │ │ │ ├── search │ │ │ ├── MainViewModel.kt │ │ │ ├── Todo.kt │ │ │ ├── TodoSearchManager.kt │ │ │ └── TodoState.kt │ │ │ └── ui │ │ │ └── theme │ │ │ ├── Color.kt │ │ │ ├── Theme.kt │ │ │ └── Type.kt │ └── res │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ └── ic_launcher_foreground.xml │ │ ├── mipmap-anydpi │ │ ├── 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 │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── hgm │ └── appsearch │ └── ExampleUnitTest.kt ├── build.gradle.kts ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | id("org.jetbrains.kotlin.android") 4 | kotlin("kapt") 5 | } 6 | 7 | android { 8 | namespace = "com.hgm.appsearch" 9 | compileSdk = 34 10 | 11 | defaultConfig { 12 | applicationId = "com.hgm.appsearch" 13 | minSdk = 26 14 | targetSdk = 33 15 | versionCode = 1 16 | versionName = "1.0" 17 | 18 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 19 | vectorDrawables { 20 | useSupportLibrary = true 21 | } 22 | } 23 | 24 | buildTypes { 25 | release { 26 | isMinifyEnabled = false 27 | proguardFiles( 28 | getDefaultProguardFile("proguard-android-optimize.txt"), 29 | "proguard-rules.pro" 30 | ) 31 | } 32 | } 33 | compileOptions { 34 | sourceCompatibility = JavaVersion.VERSION_17 35 | targetCompatibility = JavaVersion.VERSION_17 36 | } 37 | kotlinOptions { 38 | jvmTarget = "17" 39 | } 40 | buildFeatures { 41 | compose = true 42 | } 43 | composeOptions { 44 | kotlinCompilerExtensionVersion = "1.4.3" 45 | } 46 | packaging { 47 | resources { 48 | excludes += "/META-INF/{AL2.0,LGPL2.1}" 49 | } 50 | } 51 | } 52 | 53 | dependencies { 54 | 55 | implementation("androidx.core:core-ktx:1.9.0") 56 | implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") 57 | implementation("androidx.activity:activity-compose:1.8.2") 58 | implementation(platform("androidx.compose:compose-bom:2023.03.00")) 59 | implementation("androidx.compose.ui:ui") 60 | implementation("androidx.compose.ui:ui-graphics") 61 | implementation("androidx.compose.ui:ui-tooling-preview") 62 | implementation("androidx.compose.material3:material3") 63 | testImplementation("junit:junit:4.13.2") 64 | androidTestImplementation("androidx.test.ext:junit:1.1.5") 65 | androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") 66 | androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) 67 | androidTestImplementation("androidx.compose.ui:ui-test-junit4") 68 | debugImplementation("androidx.compose.ui:ui-tooling") 69 | debugImplementation("androidx.compose.ui:ui-test-manifest") 70 | 71 | // App Search 72 | implementation("androidx.appsearch:appsearch:1.1.0-alpha03") 73 | kapt("androidx.appsearch:appsearch-compiler:1.1.0-alpha03") 74 | implementation("androidx.appsearch:appsearch-local-storage:1.1.0-alpha03") 75 | } -------------------------------------------------------------------------------- /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/hgm/appsearch/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch 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.hgm.appsearch", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/hgm/appsearch/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch 2 | 3 | import android.os.Bundle 4 | import android.widget.CheckBox 5 | import androidx.activity.ComponentActivity 6 | import androidx.activity.compose.setContent 7 | import androidx.activity.viewModels 8 | import androidx.compose.foundation.background 9 | import androidx.compose.foundation.layout.Arrangement 10 | import androidx.compose.foundation.layout.Column 11 | import androidx.compose.foundation.layout.Row 12 | import androidx.compose.foundation.layout.fillMaxSize 13 | import androidx.compose.foundation.layout.fillMaxWidth 14 | import androidx.compose.foundation.layout.padding 15 | import androidx.compose.foundation.lazy.LazyColumn 16 | import androidx.compose.foundation.lazy.items 17 | import androidx.compose.material3.Checkbox 18 | import androidx.compose.material3.ExperimentalMaterial3Api 19 | import androidx.compose.material3.MaterialTheme 20 | import androidx.compose.material3.OutlinedTextField 21 | import androidx.compose.material3.Surface 22 | import androidx.compose.material3.Text 23 | import androidx.compose.runtime.Composable 24 | import androidx.compose.ui.Alignment 25 | import androidx.compose.ui.Modifier 26 | import androidx.compose.ui.tooling.preview.Preview 27 | import androidx.compose.ui.unit.dp 28 | import androidx.lifecycle.ViewModel 29 | import androidx.lifecycle.ViewModelProvider 30 | import com.hgm.appsearch.search.MainViewModel 31 | import com.hgm.appsearch.search.Todo 32 | import com.hgm.appsearch.search.TodoSearchManager 33 | import com.hgm.appsearch.ui.theme.AppSearchTheme 34 | 35 | class MainActivity : ComponentActivity() { 36 | 37 | private val viewModel: MainViewModel by viewModels(factoryProducer = { 38 | object : ViewModelProvider.Factory { 39 | override fun create(modelClass: Class): T { 40 | return MainViewModel(TodoSearchManager(applicationContext)) as T 41 | } 42 | } 43 | }) 44 | 45 | 46 | @OptIn(ExperimentalMaterial3Api::class) 47 | override fun onCreate(savedInstanceState: Bundle?) { 48 | super.onCreate(savedInstanceState) 49 | setContent { 50 | AppSearchTheme { 51 | Surface( 52 | modifier = Modifier 53 | .fillMaxSize() 54 | .background(MaterialTheme.colorScheme.background) 55 | ) { 56 | val state = viewModel.state 57 | 58 | Column( 59 | modifier = Modifier 60 | .fillMaxSize() 61 | .padding(12.dp), 62 | verticalArrangement = Arrangement.spacedBy(12.dp) 63 | ) { 64 | OutlinedTextField( 65 | value = state.searchQuery, 66 | onValueChange = viewModel::onSearchQuery, 67 | modifier = Modifier.fillMaxWidth() 68 | ) 69 | 70 | LazyColumn( 71 | modifier = Modifier 72 | .fillMaxWidth() 73 | .weight(1f), 74 | verticalArrangement = Arrangement.spacedBy(12.dp) 75 | ) { 76 | items(state.todos) { todo -> 77 | TodoItem(todo = todo, onDoneChange = { isDone -> 78 | viewModel.onDoneChange(todo, isDone) 79 | }) 80 | } 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | @Composable 90 | fun TodoItem( 91 | todo: Todo, onDoneChange: (Boolean) -> Unit, modifier: Modifier = Modifier 92 | ) { 93 | Row( 94 | modifier = modifier.fillMaxWidth(), 95 | horizontalArrangement = Arrangement.SpaceBetween, 96 | verticalAlignment = Alignment.CenterVertically 97 | ) { 98 | Column { 99 | Text(text = todo.title, style = MaterialTheme.typography.titleMedium) 100 | Text(text = todo.text, style = MaterialTheme.typography.bodyMedium) 101 | } 102 | 103 | Checkbox(checked = todo.isDone, onCheckedChange = onDoneChange) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/hgm/appsearch/search/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch.search 2 | 3 | import androidx.compose.runtime.getValue 4 | import androidx.compose.runtime.mutableStateOf 5 | import androidx.compose.runtime.setValue 6 | import androidx.lifecycle.ViewModel 7 | import androidx.lifecycle.viewModelScope 8 | import kotlinx.coroutines.Job 9 | import kotlinx.coroutines.delay 10 | import kotlinx.coroutines.launch 11 | import java.util.UUID 12 | 13 | 14 | class MainViewModel( 15 | private val todoSearchManager: TodoSearchManager 16 | ) : ViewModel() { 17 | 18 | var state by mutableStateOf(TodoState()) 19 | private set 20 | 21 | private var searchJob: Job? = null 22 | 23 | // 初始完数据之后就注释掉,否则有重复数据 24 | init { 25 | viewModelScope.launch { 26 | todoSearchManager.init() 27 | val todos = (1..100).map { 28 | Todo( 29 | namespace = "my_todos", 30 | id = UUID.randomUUID().toString(), 31 | score = 1, 32 | title = "Todo ${it + 1}", 33 | text = "desc ${it + 1}", 34 | isDone = kotlin.random.Random.nextBoolean() 35 | ) 36 | } 37 | todoSearchManager.putTodo(todos) 38 | } 39 | } 40 | 41 | 42 | fun onSearchQuery(query: String) { 43 | state = state.copy(searchQuery = query) 44 | 45 | searchJob?.cancel() 46 | searchJob = viewModelScope.launch { 47 | delay(500L)// 防抖 48 | val todos = todoSearchManager.searchTodos(query) 49 | state = state.copy(todos = todos) 50 | } 51 | } 52 | 53 | 54 | fun onDoneChange(todo: Todo, isDone: Boolean) { 55 | viewModelScope.launch { 56 | todoSearchManager.putTodo( 57 | listOf(todo.copy(isDone = isDone)) 58 | ) 59 | 60 | state = state.copy( 61 | todos = state.todos.map { 62 | if (it.id == todo.id) { 63 | it.copy(isDone = isDone) 64 | }else it 65 | } 66 | ) 67 | } 68 | } 69 | 70 | override fun onCleared() { 71 | super.onCleared() 72 | todoSearchManager.closeSession() 73 | } 74 | } -------------------------------------------------------------------------------- /app/src/main/java/com/hgm/appsearch/search/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch.search 2 | 3 | import androidx.appsearch.annotation.Document 4 | import androidx.appsearch.annotation.Document.BooleanProperty 5 | import androidx.appsearch.annotation.Document.Id 6 | import androidx.appsearch.annotation.Document.Namespace 7 | import androidx.appsearch.annotation.Document.Score 8 | import androidx.appsearch.annotation.Document.StringProperty 9 | import androidx.appsearch.app.AppSearchSchema 10 | 11 | @Document 12 | data class Todo( 13 | @Namespace 14 | val namespace: String, 15 | @Id 16 | val id: String, 17 | @Score 18 | val score: Int, 19 | @StringProperty( 20 | indexingType = AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES 21 | ) 22 | val title: String, 23 | @StringProperty( 24 | indexingType = AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES 25 | ) 26 | val text: String, 27 | @BooleanProperty 28 | val isDone: Boolean 29 | ) 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/hgm/appsearch/search/TodoSearchManager.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch.search 2 | 3 | import android.content.Context 4 | import androidx.appsearch.app.AppSearchSession 5 | import androidx.appsearch.app.PutDocumentsRequest 6 | import androidx.appsearch.app.SearchSpec 7 | import androidx.appsearch.app.SetSchemaRequest 8 | import androidx.appsearch.localstorage.LocalStorage 9 | import kotlinx.coroutines.Dispatchers 10 | import kotlinx.coroutines.withContext 11 | 12 | 13 | class TodoSearchManager( 14 | private val appContext: Context 15 | ) { 16 | // 会话 17 | private var session: AppSearchSession? = null 18 | 19 | // 初始化 20 | suspend fun init() { 21 | withContext(Dispatchers.IO) { 22 | // 通过上下文创建数据库 23 | val sessionFuture = LocalStorage.createSearchSessionAsync( 24 | LocalStorage.SearchContext.Builder( 25 | appContext, 26 | "todo" 27 | ).build() 28 | ) 29 | 30 | val setSchemaRequest = SetSchemaRequest.Builder() 31 | .addDocumentClasses(Todo::class.java) 32 | .build() 33 | 34 | // 创建完成后会返回会话,并保持打开 35 | session = sessionFuture.get() 36 | session?.setSchemaAsync(setSchemaRequest) 37 | } 38 | } 39 | 40 | // 准备数据 41 | suspend fun putTodo(todos: List): Boolean { 42 | return withContext(Dispatchers.IO) { 43 | session?.putAsync( 44 | PutDocumentsRequest.Builder() 45 | .addDocuments(todos) 46 | .build() 47 | )?.get()?.isSuccess == true 48 | } 49 | } 50 | 51 | // 搜索 52 | suspend fun searchTodos(query: String): List { 53 | return withContext(Dispatchers.IO) { 54 | val searchSpec = SearchSpec.Builder() 55 | .setSnippetCount(10)// 设置搜索结果的前10位 56 | .addFilterNamespaces("my_todos")// 过滤的命名空间 57 | .setRankingStrategy(SearchSpec.RANKING_STRATEGY_USAGE_COUNT) // 设置排序模式 58 | .build() 59 | 60 | val result = session?.search( 61 | query, 62 | searchSpec 63 | ) ?: return@withContext emptyList() 64 | 65 | val page = result.nextPageAsync.get() 66 | 67 | page.mapNotNull { 68 | if (it.genericDocument.schemaType == Todo::class.java.simpleName) { 69 | it.getDocument(Todo::class.java) 70 | } else null 71 | } 72 | } 73 | } 74 | 75 | // 关闭会话 76 | fun closeSession() { 77 | session?.close() 78 | } 79 | } -------------------------------------------------------------------------------- /app/src/main/java/com/hgm/appsearch/search/TodoState.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch.search 2 | 3 | 4 | data class TodoState( 5 | val searchQuery: String = "", 6 | val todos: List = emptyList() 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/hgm/appsearch/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple80 = Color(0xFFD0BCFF) 6 | val PurpleGrey80 = Color(0xFFCCC2DC) 7 | val Pink80 = Color(0xFFEFB8C8) 8 | 9 | val Purple40 = Color(0xFF6650a4) 10 | val PurpleGrey40 = Color(0xFF625b71) 11 | val Pink40 = Color(0xFF7D5260) -------------------------------------------------------------------------------- /app/src/main/java/com/hgm/appsearch/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch.ui.theme 2 | 3 | import android.app.Activity 4 | import android.os.Build 5 | import androidx.compose.foundation.isSystemInDarkTheme 6 | import androidx.compose.material3.MaterialTheme 7 | import androidx.compose.material3.darkColorScheme 8 | import androidx.compose.material3.dynamicDarkColorScheme 9 | import androidx.compose.material3.dynamicLightColorScheme 10 | import androidx.compose.material3.lightColorScheme 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.runtime.SideEffect 13 | import androidx.compose.ui.graphics.toArgb 14 | import androidx.compose.ui.platform.LocalContext 15 | import androidx.compose.ui.platform.LocalView 16 | import androidx.core.view.WindowCompat 17 | 18 | private val DarkColorScheme = darkColorScheme( 19 | primary = Purple80, 20 | secondary = PurpleGrey80, 21 | tertiary = Pink80 22 | ) 23 | 24 | private val LightColorScheme = lightColorScheme( 25 | primary = Purple40, 26 | secondary = PurpleGrey40, 27 | tertiary = Pink40 28 | 29 | /* Other default colors to override 30 | background = Color(0xFFFFFBFE), 31 | surface = Color(0xFFFFFBFE), 32 | onPrimary = Color.White, 33 | onSecondary = Color.White, 34 | onTertiary = Color.White, 35 | onBackground = Color(0xFF1C1B1F), 36 | onSurface = Color(0xFF1C1B1F), 37 | */ 38 | ) 39 | 40 | @Composable 41 | fun AppSearchTheme( 42 | darkTheme: Boolean = isSystemInDarkTheme(), 43 | // Dynamic color is available on Android 12+ 44 | dynamicColor: Boolean = true, 45 | content: @Composable () -> Unit 46 | ) { 47 | val colorScheme = when { 48 | dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { 49 | val context = LocalContext.current 50 | if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme( 51 | context 52 | ) 53 | } 54 | 55 | darkTheme -> DarkColorScheme 56 | else -> LightColorScheme 57 | } 58 | val view = LocalView.current 59 | if (!view.isInEditMode) { 60 | SideEffect { 61 | val window = (view.context as Activity).window 62 | window.statusBarColor = colorScheme.primary.toArgb() 63 | WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = 64 | darkTheme 65 | } 66 | } 67 | 68 | MaterialTheme( 69 | colorScheme = colorScheme, 70 | typography = Typography, 71 | content = content 72 | ) 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/hgm/appsearch/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.hgm.appsearch.ui.theme 2 | 3 | import androidx.compose.material3.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 | bodyLarge = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp, 15 | lineHeight = 24.sp, 16 | letterSpacing = 0.5.sp 17 | ) 18 | /* Other default text styles to override 19 | titleLarge = TextStyle( 20 | fontFamily = FontFamily.Default, 21 | fontWeight = FontWeight.Normal, 22 | fontSize = 22.sp, 23 | lineHeight = 28.sp, 24 | letterSpacing = 0.sp 25 | ), 26 | labelSmall = TextStyle( 27 | fontFamily = FontFamily.Default, 28 | fontWeight = FontWeight.Medium, 29 | fontSize = 11.sp, 30 | lineHeight = 16.sp, 31 | letterSpacing = 0.5.sp 32 | ) 33 | */ 34 | ) -------------------------------------------------------------------------------- /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/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/germenwong/AppSearchGuide/565ed1205f0f5e3df09809dd75d59daa5eca733e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /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 | AppSearch 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |