Page 7 Stage 2
This commit is contained in:
parent
da8d47f2b2
commit
4d35371e4a
10 changed files with 231 additions and 28 deletions
|
@ -10,10 +10,10 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "uk.kagurach.android101"
|
applicationId = "uk.kagurach.android101"
|
||||||
minSdk = 31
|
minSdk = 28
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 160
|
versionCode = 172
|
||||||
versionName = "1.6"
|
versionName = "1.7.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
@ -89,4 +89,6 @@ dependencies {
|
||||||
|
|
||||||
implementation(libs.moshi)
|
implementation(libs.moshi)
|
||||||
implementation(libs.okhttp3)
|
implementation(libs.okhttp3)
|
||||||
|
|
||||||
|
implementation(libs.ffmpeg.min)
|
||||||
}
|
}
|
|
@ -5,7 +5,10 @@
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="32" />
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
|
|
@ -60,6 +60,16 @@ public class MainActivity extends KaBaseActivity {
|
||||||
new String[]{Manifest.permission.POST_NOTIFICATIONS},
|
new String[]{Manifest.permission.POST_NOTIFICATIONS},
|
||||||
101);
|
101);
|
||||||
}
|
}
|
||||||
|
if (ContextCompat
|
||||||
|
.checkSelfPermission
|
||||||
|
(MainActivity.this, Manifest.permission.READ_MEDIA_AUDIO)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
textViewAppendString(tv, "Acquiring READ_MEDIA_AUDIO");
|
||||||
|
ActivityCompat.requestPermissions
|
||||||
|
(MainActivity.this,
|
||||||
|
new String[]{Manifest.permission.READ_MEDIA_AUDIO},
|
||||||
|
102);
|
||||||
|
}
|
||||||
textViewAppendString(tv, "Check Finished");
|
textViewAppendString(tv, "Check Finished");
|
||||||
textViewAppendString(tv, "提示:常按有惊喜");
|
textViewAppendString(tv, "提示:常按有惊喜");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,12 @@ package uk.kagurach.android101
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.media.AudioAttributes
|
||||||
|
import android.media.MediaPlayer
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.provider.MediaStore
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
|
@ -19,18 +24,27 @@ import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
import androidx.datastore.preferences.preferencesDataStore
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
import com.arthenica.ffmpegkit.FFmpegKit
|
||||||
|
import com.arthenica.ffmpegkit.ReturnCode
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import okhttp3.Call
|
import okhttp3.Call
|
||||||
import okhttp3.Callback
|
import okhttp3.Callback
|
||||||
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import uk.kagurach.android101.helper.ToastHelper
|
import uk.kagurach.android101.helper.ToastHelper
|
||||||
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
|
||||||
val Context.tgDatastore by preferencesDataStore(name = "tg_settings")
|
val Context.tgDatastore by preferencesDataStore(name = "tg_settings")
|
||||||
val DefaultAPI = stringPreferencesKey("default_api")
|
val DefaultAPI = stringPreferencesKey("default_api")
|
||||||
|
@ -59,6 +73,10 @@ class Page7 : KaBaseActivity() {
|
||||||
findViewById<Button>(R.id.P7SetAPI).setOnClickListener(FrameButtonHandler())
|
findViewById<Button>(R.id.P7SetAPI).setOnClickListener(FrameButtonHandler())
|
||||||
findViewById<ImageButton>(R.id.P7CloseResultButton).setOnClickListener(FrameButtonHandler())
|
findViewById<ImageButton>(R.id.P7CloseResultButton).setOnClickListener(FrameButtonHandler())
|
||||||
findViewById<ImageButton>(R.id.P7CloseAPIButton).setOnClickListener(FrameButtonHandler())
|
findViewById<ImageButton>(R.id.P7CloseAPIButton).setOnClickListener(FrameButtonHandler())
|
||||||
|
|
||||||
|
findViewById<Button>(R.id.P7ListenAudio).setOnClickListener(RecordButtonHandler())
|
||||||
|
findViewById<Button>(R.id.P7RecordAudio).setOnClickListener(RecordButtonHandler())
|
||||||
|
findViewById<Button>(R.id.P7SendAudio).setOnClickListener(ButtonHandler(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ButtonHandler(val activity: Activity) : OnClickListener {
|
inner class ButtonHandler(val activity: Activity) : OnClickListener {
|
||||||
|
@ -77,12 +95,11 @@ class Page7 : KaBaseActivity() {
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.P7SaveAndSetAPI -> { // 测试并保存API
|
R.id.P7SaveAndSetAPI -> { // 测试并保存API
|
||||||
tgHandler.testSelf { result ->
|
tgHandler.testSelf { result ->
|
||||||
if (result.contains("""{"ok":true}""")) {
|
if (result.contains("\"ok\":true")) {
|
||||||
runBlocking { // 成功
|
runBlocking { // 成功
|
||||||
storage.setDefaultAPI(botAPI)
|
storage.setDefaultAPI(botAPI)
|
||||||
storage.setDefaultID(chatID)
|
storage.setDefaultID(chatID)
|
||||||
}
|
}
|
||||||
ToastHelper.ShowToast("OK", baseContext)
|
|
||||||
}
|
}
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
resultTextField.text = result
|
resultTextField.text = result
|
||||||
|
@ -101,6 +118,17 @@ class Page7 : KaBaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R.id.P7SendAudio ->{ // 发送音频
|
||||||
|
tgHandler.postAudio(
|
||||||
|
audioUri,
|
||||||
|
baseContext,
|
||||||
|
){result ->
|
||||||
|
runOnUiThread {
|
||||||
|
resultTextField.text = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else -> resultTextField.text = "?"
|
else -> resultTextField.text = "?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,6 +149,54 @@ class Page7 : KaBaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner class RecordButtonHandler : OnClickListener {
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
when (v.id) {
|
||||||
|
R.id.P7RecordAudio -> {
|
||||||
|
val recordIntent = Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION)
|
||||||
|
try {
|
||||||
|
startActivityForResult(recordIntent, 0)
|
||||||
|
} catch (e : android.content.ActivityNotFoundException){
|
||||||
|
Log.e("Recorder@Android101",e.printStackTrace().toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.P7ListenAudio -> {
|
||||||
|
if (audioUri!=Uri.EMPTY){
|
||||||
|
val mMediaPlayer = MediaPlayer()
|
||||||
|
mMediaPlayer.reset()
|
||||||
|
mMediaPlayer.setAudioAttributes(
|
||||||
|
AudioAttributes.Builder()
|
||||||
|
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
mMediaPlayer.setDataSource(baseContext,audioUri)
|
||||||
|
mMediaPlayer.prepare()
|
||||||
|
mMediaPlayer.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
when (requestCode) {
|
||||||
|
0 -> { // 录音
|
||||||
|
if (resultCode == RESULT_OK && data != null){
|
||||||
|
audioUri = data.data
|
||||||
|
ToastHelper.ShowToast("Saved at ${audioUri}",this)
|
||||||
|
findViewById<Button>(R.id.P7ListenAudio).isEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
var audioUri = Uri.EMPTY
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class telegramHandler(val BOT_KEY: String, val CHATID: String) {
|
class telegramHandler(val BOT_KEY: String, val CHATID: String) {
|
||||||
|
@ -130,20 +206,6 @@ class telegramHandler(val BOT_KEY: String, val CHATID: String) {
|
||||||
fun testSelf(callBack: (String) -> Unit) {
|
fun testSelf(callBack: (String) -> Unit) {
|
||||||
val api = "getMe"
|
val api = "getMe"
|
||||||
val finalUri = "${basicUri}/${api}"
|
val finalUri = "${basicUri}/${api}"
|
||||||
postData(finalUri, callBack)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun postText(text: String, callBack: (String) -> Unit) {
|
|
||||||
if (text.isEmpty()) {
|
|
||||||
callBack("Input Something!!")
|
|
||||||
}
|
|
||||||
|
|
||||||
val api = "sendMessage"
|
|
||||||
val finalUri = "${basicUri}/${api}?chat_id=${CHATID}&text=${text}"
|
|
||||||
postData(finalUri, callBack)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun postData(finalUri: String, callBack: (String) -> Unit) {
|
|
||||||
val request = Request.Builder().url(finalUri).post("".toRequestBody()).build()
|
val request = Request.Builder().url(finalUri).post("".toRequestBody()).build()
|
||||||
val call = client.newCall(request)
|
val call = client.newCall(request)
|
||||||
call.enqueue(object : Callback {
|
call.enqueue(object : Callback {
|
||||||
|
@ -159,6 +221,78 @@ class telegramHandler(val BOT_KEY: String, val CHATID: String) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun postText(text: String, callBack: (String) -> Unit) {
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
callBack("Input Something!!")
|
||||||
|
}
|
||||||
|
|
||||||
|
val api = "sendMessage"
|
||||||
|
val finalUri = "${basicUri}/${api}?chat_id=${CHATID}&text=${text}"
|
||||||
|
val request = Request.Builder().url(finalUri).post("".toRequestBody()).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 postAudio(audioUri: Uri,context: Context,callBack: (String) -> Unit) {
|
||||||
|
if (audioUri == Uri.EMPTY){
|
||||||
|
callBack("Sorry Please Record First")
|
||||||
|
}
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
RequestBody.create("audio/ogg".toMediaTypeOrNull(),File("${context.cacheDir.path}/decoded.ogg"))
|
||||||
|
)
|
||||||
|
.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}")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -193,4 +327,4 @@ class TGStorage(val context: Context) {
|
||||||
private val getDefaultIDFlow: Flow<String> = context.tgDatastore.data.map { preferences ->
|
private val getDefaultIDFlow: Flow<String> = context.tgDatastore.data.map { preferences ->
|
||||||
preferences[DefaultID] ?: ""
|
preferences[DefaultID] ?: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:minHeight="500dp"
|
android:layout_weight="6"
|
||||||
>
|
>
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_hello"
|
android:id="@+id/tv_hello"
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
android:textSize="15sp"
|
android:textSize="15sp"
|
||||||
android:visibility="visible" />
|
android:visibility="visible" />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_marginHorizontal="15dp"
|
||||||
android:text="@string/settings"
|
android:text="@string/settings"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -49,7 +51,7 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginVertical="10dp"
|
android:layout_marginVertical="10dp"
|
||||||
android:layout_marginHorizontal="15dp"
|
android:layout_marginHorizontal="15dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1.5"
|
||||||
android:text="@string/next_page"
|
android:text="@string/next_page"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
android:backgroundTint="?colorSecondary" />
|
android:backgroundTint="?colorSecondary" />
|
||||||
|
|
|
@ -32,7 +32,9 @@
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="50dp" />
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -41,7 +43,8 @@
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="350dp"
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="8"
|
||||||
android:layout_marginStart="10dp">
|
android:layout_marginStart="10dp">
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -59,7 +62,8 @@
|
||||||
android:text="@string/ai_ready"/>
|
android:text="@string/ai_ready"/>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="130dp"
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="3"
|
||||||
android:layout_marginHorizontal="5dp"
|
android:layout_marginHorizontal="5dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,47 @@
|
||||||
android:id="@+id/P7SendMessageButton"
|
android:id="@+id/P7SendMessageButton"
|
||||||
android:layout_width="80dp"
|
android:layout_width="80dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="send message"
|
android:text="@string/send_text"
|
||||||
|
android:textAllCaps="false"
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_marginHorizontal="15dp"
|
||||||
|
android:layout_marginVertical="5dp"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/P7RecordAudio"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/record_audio"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:backgroundTint="?colorTertiary"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/P7ListenAudio"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/play"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:backgroundTint="?colorSecondary"
|
||||||
|
android:enabled="false"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/P7SendAudio"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/send"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
|
|
|
@ -59,4 +59,8 @@
|
||||||
<string name="show_callback">显示回调</string>
|
<string name="show_callback">显示回调</string>
|
||||||
<string name="save_and_test">测试并保存</string>
|
<string name="save_and_test">测试并保存</string>
|
||||||
<string name="require_api">请输入API Key 和 Chat ID</string>
|
<string name="require_api">请输入API Key 和 Chat ID</string>
|
||||||
|
<string name="send_text">发送文字</string>
|
||||||
|
<string name="record_audio">录音</string>
|
||||||
|
<string name="send">发送</string>
|
||||||
|
<string name="play">播放</string>
|
||||||
</resources>
|
</resources>
|
|
@ -61,4 +61,8 @@
|
||||||
<string name="show_callback">Show Callback</string>
|
<string name="show_callback">Show Callback</string>
|
||||||
<string name="save_and_test">Save And Test</string>
|
<string name="save_and_test">Save And Test</string>
|
||||||
<string name="require_api">Please Fill API Key and Chat ID</string>
|
<string name="require_api">Please Fill API Key and Chat ID</string>
|
||||||
|
<string name="send_text">Send text</string>
|
||||||
|
<string name="record_audio">Record Audio</string>
|
||||||
|
<string name="send">Send</string>
|
||||||
|
<string name="play">Play</string>
|
||||||
</resources>
|
</resources>
|
|
@ -24,6 +24,7 @@ datastoreRxjava3 = "1.1.1"
|
||||||
androidxWork = "2.9.0"
|
androidxWork = "2.9.0"
|
||||||
okHttp3 = "4.9.3"
|
okHttp3 = "4.9.3"
|
||||||
moshiJson = "1.15.1"
|
moshiJson = "1.15.1"
|
||||||
|
ffmpegKit = "6.0-2"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
@ -58,6 +59,8 @@ androidx-work = { group = "androidx.work", name="work-runtime", version.ref = "a
|
||||||
okhttp3 = { group = "com.squareup.okhttp3", name="okhttp",version.ref="okHttp3"}
|
okhttp3 = { group = "com.squareup.okhttp3", name="okhttp",version.ref="okHttp3"}
|
||||||
moshi = {group="com.squareup.moshi",name="moshi-kotlin",version.ref="moshiJson"}
|
moshi = {group="com.squareup.moshi",name="moshi-kotlin",version.ref="moshiJson"}
|
||||||
|
|
||||||
|
ffmpeg-min = {group="com.arthenica",name="ffmpeg-kit-full",version.ref="ffmpegKit"}
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||||
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
|
Loading…
Reference in a new issue