Initial public release.
This commit is contained in:
parent
ed31acd60f
commit
58d87b11b7
249 changed files with 15831 additions and 4 deletions
104
subapp-sample/README.md
Normal file
104
subapp-sample/README.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# KTag Sample Subapp
|
||||
|
||||
A minimal Jetpack Compose subapp template for creating new KTag applications.
|
||||
|
||||
## Overview
|
||||
|
||||
The Sample subapp provides a starting point for creating new subapps in the KTag ecosystem. It demonstrates the minimal required structure and can be copied as a template for new functionality.
|
||||
|
||||
## Architecture
|
||||
|
||||
The simplest possible subapp structure:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ SampleActivity │
|
||||
│ (Compose Host) │
|
||||
│ • Single "Hello World" screen │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
src/main/java/club/clubk/ktag/apps/sample/
|
||||
├── SampleActivity.kt # Main activity with Compose UI
|
||||
├── SampleSubApp.kt # Subapp registration
|
||||
└── SampleInitializer.kt # Startup initializer
|
||||
```
|
||||
|
||||
## Creating a New Subapp
|
||||
|
||||
To create a new subapp based on this template:
|
||||
|
||||
1. **Copy the module**: Duplicate `subapp-sample` directory
|
||||
2. **Rename the package**: Update package name in all files
|
||||
3. **Update build.gradle.kts**: Change namespace
|
||||
4. **Register the subapp**: Update `SampleSubApp` with new ID, name, icon
|
||||
5. **Add to settings.gradle.kts**: Include new module
|
||||
6. **Add dependency**: Include in main app's dependencies
|
||||
|
||||
## Required Components
|
||||
|
||||
### SubApp Interface
|
||||
|
||||
Every subapp must implement the `SubApp` interface:
|
||||
|
||||
```kotlin
|
||||
class MySubApp : SubApp {
|
||||
override val id = "myapp" // Unique identifier
|
||||
override val name = "My App" // Display name
|
||||
override val icon = R.drawable.ic_myapp // Launcher icon
|
||||
|
||||
override fun createIntent(context: Context): Intent {
|
||||
return Intent(context, MyActivity::class.java)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Initializer
|
||||
|
||||
Register the subapp at startup:
|
||||
|
||||
```kotlin
|
||||
class MyInitializer : Initializer<Unit> {
|
||||
override fun create(context: Context) {
|
||||
SubAppRegistry.register(MySubApp())
|
||||
}
|
||||
|
||||
override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
|
||||
}
|
||||
```
|
||||
|
||||
### AndroidManifest.xml
|
||||
|
||||
Declare the activity and initializer:
|
||||
|
||||
```xml
|
||||
<activity android:name=".MyActivity" android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup">
|
||||
<meta-data
|
||||
android:name=".MyInitializer"
|
||||
android:value="androidx.startup" />
|
||||
</provider>
|
||||
```
|
||||
|
||||
## Optional Features
|
||||
|
||||
For more complex subapps, consider adding:
|
||||
|
||||
| Feature | Reference |
|
||||
|---------|-----------|
|
||||
| Settings | See `subapp-koth` or `subapp-medic` |
|
||||
| MQTT | Implement `SettingsSubApp` interface |
|
||||
| BLE | See `subapp-bletool` or `subapp-koth` |
|
||||
| USB Serial | See `subapp-terminal` |
|
||||
| ViewModel | See `subapp-koth` or `subapp-medic` |
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Jetpack Compose (Material3)
|
||||
- AndroidX Startup (for initialization)
|
||||
41
subapp-sample/build.gradle.kts
Normal file
41
subapp-sample/build.gradle.kts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "club.clubk.ktag.apps.sample"
|
||||
compileSdk = 36
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":core"))
|
||||
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.compose.ui)
|
||||
implementation(libs.androidx.compose.material3)
|
||||
implementation(libs.androidx.startup)
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
compilerOptions {
|
||||
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
|
||||
}
|
||||
}
|
||||
20
subapp-sample/src/main/AndroidManifest.xml
Normal file
20
subapp-sample/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name=".SampleActivity"
|
||||
android:exported="false"
|
||||
android:label="Sample SubApp" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
android:exported="false">
|
||||
<meta-data
|
||||
android:name="club.clubk.ktag.apps.sample.SampleInitializer"
|
||||
android:value="androidx.startup" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package club.clubk.ktag.apps.sample
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
class SampleActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
MaterialTheme {
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
Text(
|
||||
text = "Hello from Sample SubApp!",
|
||||
style = MaterialTheme.typography.headlineMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package club.clubk.ktag.apps.sample
|
||||
|
||||
import android.content.Context
|
||||
import androidx.startup.Initializer
|
||||
import club.clubk.ktag.apps.core.SubAppRegistry
|
||||
|
||||
class SampleInitializer : Initializer<Unit> {
|
||||
override fun create(context: Context) {
|
||||
SubAppRegistry.register(SampleSubApp())
|
||||
}
|
||||
|
||||
override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package club.clubk.ktag.apps.sample
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import club.clubk.ktag.apps.core.SubApp
|
||||
|
||||
class SampleSubApp : SubApp {
|
||||
override val id = "sample"
|
||||
override val name = "Sample"
|
||||
override val icon = R.drawable.ic_sample
|
||||
|
||||
override fun createIntent(context: Context): Intent {
|
||||
return Intent(context, SampleActivity::class.java)
|
||||
}
|
||||
}
|
||||
43
subapp-sample/src/main/res/drawable/ic_sample.xml
Normal file
43
subapp-sample/src/main/res/drawable/ic_sample.xml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="83.962"
|
||||
android:viewportHeight="84.052"
|
||||
android:tint="#333333"
|
||||
android:alpha="0.6">
|
||||
<group android:scaleX="0.83244103"
|
||||
android:scaleY="0.8333333"
|
||||
android:translateX="7.034293"
|
||||
android:translateY="7.0043335">
|
||||
<path
|
||||
android:pathData="m14.681,64.127q-0.305,-0.198 -0.611,-0.431 -0.287,-0.251 -0.611,-0.431 -1.796,-1.042 -3.538,-0.7 -1.742,0.341 -3.251,1.67l-0.269,0.233l2.299,2.299q0.539,-0.431 0.934,-0.575 0.377,-0.162 0.736,-0.09 0.377,0.054 0.772,0.341 0.413,0.269 0.952,0.7zM20.249,69.299q-1.042,-1.042 -2.065,-1.419 -1.006,-0.395 -1.976,-0.323 -0.988,0.054 -1.904,0.467 -0.934,0.395 -1.796,0.934 -0.862,0.503 -1.634,1.06 -0.79,0.539 -1.491,0.88 -0.7,0.341 -1.293,0.395 -0.611,0.036 -1.096,-0.449 -0.377,-0.377 -0.485,-0.736 -0.126,-0.377 -0.036,-0.718 0.072,-0.359 0.305,-0.665 0.216,-0.323 0.521,-0.629l-2.263,-2.263l-0.108,0.108q-0.916,0.916 -1.491,1.922 -0.593,0.988 -0.718,2.012 -0.126,1.024 0.287,2.083 0.395,1.042 1.437,2.083 0.934,0.934 1.868,1.257 0.934,0.287 1.868,0.18 0.916,-0.126 1.832,-0.539 0.898,-0.431 1.76,-0.934 0.862,-0.539 1.67,-1.06 0.808,-0.521 1.527,-0.844 0.718,-0.323 1.347,-0.305 0.629,-0.018 1.149,0.503 0.377,0.377 0.485,0.772 0.126,0.377 0.054,0.772 -0.09,0.377 -0.305,0.736 -0.216,0.359 -0.503,0.682l2.353,2.353q0.233,-0.269 0.395,-0.467 0.18,-0.216 0.305,-0.413 0.162,-0.198 0.287,-0.431 0.144,-0.216 0.323,-0.539 0.431,-0.754 0.647,-1.616 0.198,-0.88 0.144,-1.724 -0.072,-0.862 -0.413,-1.67 -0.341,-0.808 -0.988,-1.455zM18.219,79.016 L15.831,76.663q-0.647,0.539 -1.096,0.772 -0.431,0.216 -0.844,0.162 -0.413,-0.054 -0.898,-0.323 -0.485,-0.269 -1.221,-0.718l-2.676,2.963q2.012,1.904 3.951,2.047 1.94,0.144 4.005,-1.527 0.323,-0.251 0.593,-0.521 0.287,-0.251 0.575,-0.503z"
|
||||
android:strokeWidth="0.446"
|
||||
android:fillColor="#323031"
|
||||
android:strokeColor="#323031"/>
|
||||
<path
|
||||
android:pathData="m36.521,60.032 l-16.991,-8.154l-3.233,3.233l8.244,16.901l3.197,-3.197l-5.676,-10.381q-0.305,-0.593 -0.647,-1.114 -0.359,-0.539 -0.718,-1.078 1.401,1.114 2.981,1.904 1.598,0.772 3.161,1.616l-1.383,1.419 1.581,2.946l2.802,-2.802l3.52,1.868z"
|
||||
android:strokeWidth="0.446"
|
||||
android:fillColor="#323031"
|
||||
android:strokeColor="#323031"/>
|
||||
<path
|
||||
android:pathData="m51.051,45.501l-12.572,-12.572l-2.622,2.622l12.572,12.572zM40.329,42.394l-5.658,-5.658l-0.216,0.216q1.778,3.035 3.502,6.053 1.724,2.981 3.7,5.891 -2.963,-1.922 -5.963,-3.628 -3.017,-1.724 -6.071,-3.484l-0.126,0.126l5.765,5.765q0.072,0.072 0.341,0.233 0.251,0.144 0.557,0.305 0.287,0.144 0.557,0.305 0.287,0.144 0.413,0.233l6.107,4.562l2.838,-2.838l-4.67,-6.214q-0.09,-0.126 -0.251,-0.395 -0.144,-0.287 -0.287,-0.575 -0.162,-0.305 -0.305,-0.557 -0.162,-0.269 -0.233,-0.341zM40.904,55.649l-12.572,-12.572l-2.64,2.64l12.572,12.572z"
|
||||
android:strokeWidth="0.446"
|
||||
android:fillColor="#323031"
|
||||
android:strokeColor="#323031"/>
|
||||
<path
|
||||
android:pathData="m54.284,25.35q-1.078,-1.078 -2.047,-1.652 -0.988,-0.593 -1.904,-0.647 -0.934,-0.072 -1.868,0.395 -0.952,0.449 -1.958,1.455l-1.868,1.868l2.299,2.299l0.108,-0.108q0.575,-0.575 1.042,-1.042 0.485,-0.485 0.988,-0.665 0.503,-0.18 1.096,0.054 0.593,0.198 1.383,0.988 0.575,0.575 0.808,1.024 0.233,0.449 0.18,0.862 -0.036,0.395 -0.323,0.79 -0.305,0.377 -0.754,0.826l-0.898,0.898l2.281,2.281l1.419,-1.419q1.06,-1.06 1.652,-2.012 0.593,-0.988 0.629,-1.958 0.018,-0.988 -0.539,-2.012 -0.539,-1.042 -1.724,-2.227zM55.847,40.706l-12.572,-12.572l-2.82,2.82l12.572,12.572z"
|
||||
android:strokeWidth="0.446"
|
||||
android:fillColor="#323031"
|
||||
android:strokeColor="#323031"/>
|
||||
<path
|
||||
android:pathData="m67.108,29.445l-12.59,-12.59l-2.856,2.856l12.59,12.59zM73.053,23.5l-2.353,-2.353l-4.616,4.616l2.353,2.353z"
|
||||
android:strokeWidth="0.446"
|
||||
android:fillColor="#323031"
|
||||
android:strokeColor="#323031"/>
|
||||
<path
|
||||
android:pathData="m73.358,2.684l-2.335,-2.335l-4.975,4.975l2.335,2.335zM77.651,7.91l-2.263,-2.263l-4.508,4.508l2.263,2.263zM83.739,12.813l-2.335,-2.335l-5.101,5.101l2.335,2.335zM77.256,19.297l-12.59,-12.59l-2.802,2.802l12.59,12.59z"
|
||||
android:strokeWidth="0.446"
|
||||
android:fillColor="#323031"
|
||||
android:strokeColor="#323031"/>
|
||||
</group>
|
||||
</vector>
|
||||
Loading…
Add table
Add a link
Reference in a new issue