Do AIDL Now

This commit is contained in:
icewithcola 2024-09-10 15:11:18 +08:00
parent ec813eda1b
commit b2dd0735d6
14 changed files with 361 additions and 325 deletions

View file

@ -1,263 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="direct_access_persist.xml">
<option name="deviceSelectionList">
<list>
<PersistentDeviceSelectionData>
<option name="api" value="27" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="F01L" />
<option name="id" value="F01L" />
<option name="manufacturer" value="FUJITSU" />
<option name="name" value="F-01L" />
<option name="screenDensity" value="360" />
<option name="screenX" value="720" />
<option name="screenY" value="1280" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="28" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="SH-01L" />
<option name="id" value="SH-01L" />
<option name="manufacturer" value="SHARP" />
<option name="name" value="AQUOS sense2 SH-01L" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="samsung" />
<option name="codename" value="a51" />
<option name="id" value="a51" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy A51" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="akita" />
<option name="id" value="akita" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="b0q" />
<option name="id" value="b0q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S22 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="32" />
<option name="brand" value="google" />
<option name="codename" value="bluejay" />
<option name="id" value="bluejay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="crownqlteue" />
<option name="id" value="crownqlteue" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2220" />
<option name="screenY" value="1080" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm3q" />
<option name="id" value="dm3q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S23 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix_camera" />
<option name="id" value="felix_camera" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold (Camera-enabled)" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8uwifi" />
<option name="id" value="gts8uwifi" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8 Ultra" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1848" />
<option name="screenY" value="2960" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="husky" />
<option name="id" value="husky" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8 Pro" />
<option name="screenDensity" value="390" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="java" />
<option name="id" value="java" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="G20" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="lynx" />
<option name="id" value="lynx" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="google" />
<option name="codename" value="oriole" />
<option name="id" value="oriole" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="panther" />
<option name="id" value="panther" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="samsung" />
<option name="codename" value="q2q" />
<option name="id" value="q2q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold3" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1768" />
<option name="screenY" value="2208" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q5q" />
<option name="id" value="q5q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold5" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1812" />
<option name="screenY" value="2176" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="r11" />
<option name="id" value="r11" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Watch" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
<option name="type" value="WEAR_OS" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="redfin" />
<option name="id" value="redfin" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 5" />
<option name="screenDensity" value="440" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="shiba" />
<option name="id" value="shiba" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="tangorpro" />
<option name="id" value="tangorpro" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Tablet" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="x1q" />
<option name="id" value="x1q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S20" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1440" />
<option name="screenY" value="3200" />
</PersistentDeviceSelectionData>
</list>
</option>
</component>
</project>

View file

@ -16,6 +16,14 @@ android {
versionName = "1.7.4"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
externalNativeBuild {
cmake {
cppFlags += ""
}
}
}
buildTypes {
@ -37,6 +45,7 @@ android {
buildFeatures {
compose = true
viewBinding = true
aidl = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
@ -50,6 +59,18 @@ android {
aaptOptions {
noCompress("tflite")
}
splits {
abi {
isEnable = true
reset()
include("arm64-v8a","x86_64")
}
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
@ -82,6 +103,7 @@ dependencies {
implementation(libs.androidx.camera.view)
implementation(libs.androidx.camera.lifecycle)
implementation(libs.androidx.camera.camera2)
implementation(libs.androidx.lifecycle.runtime.compose.android)
testImplementation(libs.junit)
@ -93,6 +115,8 @@ dependencies {
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
debugImplementation(libs.leakcanary.android)
implementation(libs.moshi)
implementation(libs.okhttp3)

View file

@ -26,6 +26,11 @@
android:supportsRtl="false"
android:theme="@style/Theme.Android101"
android:usesCleartextTraffic="true">
<activity
android:name=".world2.World2P1"
android:exported="true"
android:label="@string/title_activity_world2_p1"
android:theme="@style/Theme.Android101" />
<activity
android:name=".additionalActivity.CameraXActivity"
android:exported="false" />

View file

@ -0,0 +1,8 @@
package uk.kagurach.kmb;
import uk.kagurach.kmb.KMessage;
interface IKaguraMessageBus {
List<KMessage> getMessageList();
boolean sendMessage(in Person person);
}

View file

@ -0,0 +1,3 @@
package uk.kagurach.kmb;
parcelable KMessage;

View file

@ -7,7 +7,6 @@ import android.graphics.BitmapFactory
import android.media.AudioAttributes
import android.media.MediaPlayer
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
@ -22,17 +21,20 @@ import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.annotation.RequiresApi
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import androidx.lifecycle.lifecycleScope
import com.arthenica.ffmpegkit.FFmpegKit
import com.arthenica.ffmpegkit.ReturnCode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.Call
import okhttp3.Callback
@ -49,13 +51,11 @@ import org.tensorflow.lite.task.vision.classifier.Classifications
import org.tensorflow.lite.task.vision.classifier.ImageClassifier
import org.tensorflow.lite.task.vision.classifier.ImageClassifier.ImageClassifierOptions
import uk.kagurach.android101.additionalActivity.CameraXActivity
import uk.kagurach.android101.helper.PageHelper
import uk.kagurach.android101.helper.ToastHelper
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.InputStream
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
val Context.tgDatastore by preferencesDataStore(name = "tg_settings")
@ -64,6 +64,7 @@ val DefaultID = stringPreferencesKey("default_id")
class Page7 : KaBaseActivity() {
lateinit var storage: TGStorage
lateinit var pageHelper: PageHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -75,6 +76,7 @@ class Page7 : KaBaseActivity() {
insets
}
storage = TGStorage(this)
pageHelper = PageHelper(this, Page6::class.java, MainActivity::class.java)
findViewById<EditText>(R.id.Page7BotID).setText(runBlocking { storage.getDefaultAPI() })
findViewById<EditText>(R.id.Page7ChatID).setText(runBlocking { storage.getDefaultID() })
@ -104,6 +106,10 @@ class Page7 : KaBaseActivity() {
findViewById<ImageButton>(R.id.P7CloseResultButton).setOnClickListener(FrameButtonHandler())
findViewById<ImageButton>(R.id.P7CloseAPIButton).setOnClickListener(FrameButtonHandler())
findViewById<ImageButton>(R.id.P7CloseShowPicButton).setOnClickListener(FrameButtonHandler())
// PageHelper
findViewById<Button>(R.id.P7NextPage).setOnClickListener(pageHelper.pageButtonHandler)
findViewById<Button>(R.id.P7NextPage).setOnLongClickListener(pageHelper.longClickHandler)
}
inner class ButtonHandler(val activity: Activity) : OnClickListener {
@ -124,12 +130,12 @@ class Page7 : KaBaseActivity() {
R.id.P7SaveAndSetAPI -> { // 测试并保存API
tgHandler.testSelf { result ->
if (result.contains("\"ok\":true")) {
runBlocking { // 成功
lifecycleScope.launch { // 成功
storage.setDefaultAPI(botAPI)
storage.setDefaultID(chatID)
}
runOnUiThread{
ToastHelper.ShowToast("OKAY",baseContext)
runOnUiThread {
ToastHelper.ShowToast("OKAY", baseContext)
}
}
runOnUiThread {
@ -147,8 +153,8 @@ class Page7 : KaBaseActivity() {
}
tgHandler.postText(text) { result ->
if (result.contains("\"ok\":true")) {
runOnUiThread{
ToastHelper.ShowToast("OKAY",baseContext)
runOnUiThread {
ToastHelper.ShowToast("OKAY", baseContext)
}
}
runOnUiThread {
@ -163,8 +169,8 @@ class Page7 : KaBaseActivity() {
baseContext,
) { result ->
if (result.contains("\"ok\":true")) {
runOnUiThread{
ToastHelper.ShowToast("OKAY",baseContext)
runOnUiThread {
ToastHelper.ShowToast("OKAY", baseContext)
}
}
runOnUiThread {
@ -176,8 +182,8 @@ class Page7 : KaBaseActivity() {
R.id.P7SendPhoto -> { // 发送照片
tgHandler.postImage(photoPath) { result ->
if (result.contains("\"ok\":true")) {
runOnUiThread{
ToastHelper.ShowToast("OKAY",baseContext)
runOnUiThread {
ToastHelper.ShowToast("OKAY", baseContext)
}
}
runOnUiThread {
@ -246,7 +252,7 @@ class Page7 : KaBaseActivity() {
}
}
inner class RecognizePhoto(val context: Context) : OnClickListener{
inner class RecognizePhoto(val context: Context) : OnClickListener {
override fun onClick(v: View) {
// Initialization
val options =
@ -263,14 +269,16 @@ class Page7 : KaBaseActivity() {
// Run
val imageClassifier =
ImageClassifier.createFromFileAndOptions(file,options)
ImageClassifier.createFromFileAndOptions(file, options)
val results: List<Classifications> = imageClassifier.classify(
TensorImage.fromBitmap(BitmapFactory.decodeFile(photoPath))
)
val resultName = results.first().toString().split("\"")[1].split("\"").first()
val resultScore = results.first().toString().split("score=").last().split("index").first()
findViewById<TextView>(R.id.P7ViewPhotoRecognizeResult).text = "${resultName}:${resultScore}"
val resultScore =
results.first().toString().split("score=").last().split("index").first()
findViewById<TextView>(R.id.P7ViewPhotoRecognizeResult).text =
"${resultName}:${resultScore}"
}
}
@ -356,54 +364,59 @@ class telegramHandler(val BOT_KEY: String, val CHATID: String) {
callBack("Sorry Please Record First")
return
}
// Copy to local
val inputStream: InputStream = context.contentResolver.openInputStream(audioUri) ?: return
val bytes = inputStream.readBytes()
val file = File(context.cacheDir.path + "/source.m4a")
file.writeBytes(bytes)
// Use a tread pool
val pool = CoroutineScope(Dispatchers.Default)
pool.launch {
// Copy to local
val inputStream: InputStream =
context.contentResolver.openInputStream(audioUri) ?: return@launch
val bytes = inputStream.readBytes()
val file = File(context.cacheDir.path + "/source.m4a")
file.writeBytes(bytes)
// Convert to ogg
val session =
FFmpegKit.execute("-i ${context.cacheDir.path}/source.m4a -acodec libvorbis -aq 4 -vn -ac 2 -map_metadata 0 -y -f ogg ${context.cacheDir.path}/decoded.ogg")
if (!ReturnCode.isSuccess(session.getReturnCode())) {
// FAILURE
Log.d(
"FFmpeg@Android101", String.format(
"Command failed with state %s and rc %s.%s",
session.getState(), session.getReturnCode(), session.getFailStackTrace()
// Convert to ogg
val session =
FFmpegKit.execute("-i ${context.cacheDir.path}/source.m4a -acodec libvorbis -aq 4 -vn -ac 2 -map_metadata 0 -y -f ogg ${context.cacheDir.path}/decoded.ogg")
if (!ReturnCode.isSuccess(session.getReturnCode())) {
// FAILURE
Log.d(
"FFmpeg@Android101", String.format(
"Command failed with state %s and rc %s.%s",
session.getState(), session.getReturnCode(), session.getFailStackTrace()
)
)
)
return
return@launch
}
val api = "sendVoice"
val finalUri = "${basicUri}/${api}?chat_id=${CHATID}&voice=attach%3A%2F%2Fvoice"
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(
"voice", "decoded.ogg",
File("${context.cacheDir.path}/decoded.ogg").asRequestBody("audio/ogg".toMediaTypeOrNull())
)
.build()
val request = Request.Builder()
.url(finalUri)
.header("Content-Type", "multipart/form-data")
.post(requestBody)
.build()
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("TgHelper", e.printStackTrace().toString())
callBack("${e.printStackTrace()}")
}
override fun onResponse(call: Call, response: Response) {
val responseCode = response.code
val responseBody = response.body?.string()
callBack("${responseCode},${responseBody}")
}
})
}
val api = "sendVoice"
val finalUri = "${basicUri}/${api}?chat_id=${CHATID}&voice=attach%3A%2F%2Fvoice"
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(
"voice", "decoded.ogg",
File("${context.cacheDir.path}/decoded.ogg").asRequestBody("audio/ogg".toMediaTypeOrNull())
)
.build()
val request = Request.Builder()
.url(finalUri)
.header("Content-Type", "multipart/form-data")
.post(requestBody)
.build()
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("TgHelper", e.printStackTrace().toString())
callBack("${e.printStackTrace()}")
}
override fun onResponse(call: Call, response: Response) {
val responseCode = response.code
val responseBody = response.body?.string()
callBack("${responseCode},${responseBody}")
}
})
}
fun postImage(photoPath: String, callBack: (String) -> Unit) {

View file

@ -0,0 +1,106 @@
package uk.kagurach.android101.world2
import android.os.Bundle
import android.widget.EditText
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.collection.mutableIntSetOf
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import uk.kagurach.android101.R
import uk.kagurach.android101.world2.ui.theme.Android101Theme
import kotlin.random.Random
import kotlin.random.nextInt
data class DiceUiState(
val currentDieValue: Int? = null,
val lastDieValue: Int? = null,
val numberOfRolls: Int = 0
)
class World2P1 : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val model = ViewModelProvider(this)[DiceRollViewModel::class]
enableEdgeToEdge()
setContent {
Android101Theme {
MyComposable(model)
}
}
}
class DiceRollViewModel: ViewModel(){
private val _uiState = MutableStateFlow(DiceUiState())
val uiState = _uiState.asStateFlow()
private val scope = CoroutineScope(Dispatchers.Default)
fun rollDice() {
scope.run {
_uiState.update { currentState ->
currentState.copy(
lastDieValue = currentState.currentDieValue,
currentDieValue = Random.nextInt(1..6),
numberOfRolls = currentState.numberOfRolls+1
)
}
}
}
}
@Composable
private fun MyComposable(
viewModel: DiceRollViewModel
) {
val uiState by viewModel.uiState.collectAsState()
Column(
modifier = Modifier.padding(
top = WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
)
) {
Text(
text = getString(R.string.kagurachat_name),
fontSize = 25.sp,
modifier = Modifier.padding(start = 5.dp)
)
Text(text = "Current:${uiState.currentDieValue}\nLast:${uiState.lastDieValue}")
Button(onClick = {
viewModel.rollDice()
}){
Text(text = "Roll")
}
Text(text = "${uiState.numberOfRolls} times")
}
}
}

View file

@ -0,0 +1,61 @@
package uk.kagurach.android101.world2.ui.theme
import android.app.Activity
import androidx.compose.ui.graphics.Color
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme(
primary = Color(3, 169, 244, 255),
secondary = Color(0, 188, 212, 255),
tertiary = Color(144, 202, 249, 255),
error = Color(229, 57, 53, 255)
)
private val LightColorScheme = lightColorScheme(
primary = Color(2, 119, 189, 255),
secondary = Color(106, 27, 154, 255),
tertiary = Color(0, 121, 107, 255),
error = Color(136, 14, 79, 255)
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun Android101Theme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}

View file

@ -0,0 +1,34 @@
package uk.kagurach.android101.world2.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)

View file

@ -0,0 +1,11 @@
package uk.kagurach.kmb
import android.app.Service
import android.content.Intent
import android.os.IBinder
class KMServer: Service() {
override fun onBind(intent: Intent?): IBinder? {
TODO("Not yet implemented")
}
}

View file

@ -0,0 +1,26 @@
package uk.kagurach.kmb
import android.os.Parcel
import android.os.Parcelable
class KMessage(var name: String) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString()?:"")
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(name)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<KMessage> {
override fun createFromParcel(parcel: Parcel): KMessage {
return KMessage(parcel)
}
override fun newArray(size: Int): Array<KMessage?> {
return arrayOfNulls(size)
}
}
}

View file

@ -69,4 +69,6 @@
<string name="shot">拍照</string>
<string name="retake">重拍</string>
<string name="text_message">这是文本消息喵</string>
<string name="title_activity_world2_p1">" 新世界"</string>
<string name="kagurachat_name">Ka聊</string>
</resources>

View file

@ -71,4 +71,6 @@
<string name="shot">Shot</string>
<string name="retake">Retake</string>
<string name="text_message">Text Message</string>
<string name="title_activity_world2_p1">New World</string>
<string name="kagurachat_name">Kagura Chat</string>
</resources>

View file

@ -7,6 +7,7 @@ junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
appcompat = "1.7.0"
leakcanaryAndroid = "2.14"
material = "1.12.0"
activity = "1.9.1"
constraintlayout = "2.1.4"
@ -28,6 +29,7 @@ ffmpegKit = "6.0-2"
cameraX = "1.3.4"
cameraView = "1.3.4"
tensorFlow = "0.4.4"
lifecycleRuntimeComposeAndroid = "2.8.4"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@ -36,6 +38,7 @@ junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakcanaryAndroid" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
@ -69,6 +72,7 @@ moshi = { group = "com.squareup.moshi", name = "moshi-kotlin", version.ref = "mo
ffmpeg-min = { group = "com.arthenica", name = "ffmpeg-kit-full", version.ref = "ffmpegKit" }
tensorflow-lite-gpu-delegate-plugin = { group = "org.tensorflow", name = "tensorflow-lite-gpu-delegate-plugin", version.ref = "tensorFlow" }
tensorflow-lite-task-vision = { group = "org.tensorflow", name = "tensorflow-lite-task-vision", version.ref = "tensorFlow" }
androidx-lifecycle-runtime-compose-android = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose-android", version.ref = "lifecycleRuntimeComposeAndroid" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }