package com.example.flomo_ai import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle import android.view.Gravity import android.widget.Button import android.widget.EditText import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import com.google.android.material.tabs.TabLayout import com.google.gson.Gson import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response import okhttp3.RequestBody.Companion.toRequestBody import com.google.gson.JsonObject import okhttp3.MediaType.Companion.toMediaType import com.google.gson.reflect.TypeToken import android.util.Log import java.io.IOException import java.net.UnknownHostException import org.json.JSONObject import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri import java.io.InputStream import android.content.Context import android.app.Activity import android.widget.ImageView // 定义请求体数据类 data class ChatRequest( val model: String, val messages: List ) data class Message( val role: String, val content: String ) // 从返回的 JSON 响应中提取标签列表 fun extractLabels(responseBody: String): List? { try { // 假设 responseBody 中包含一个完整的 JSON 对象,我们需要先提取出其中的 content 部分 val fullJsonObject = Gson().fromJson(responseBody, JsonObject::class.java) val choicesArray = fullJsonObject.getAsJsonArray("choices") if (choicesArray.size() > 0) { val firstChoice = choicesArray.get(0).asJsonObject val messageObject = firstChoice.get("message").asJsonObject val content = messageObject.get("content").asString // 从 content 中提取出 labels val startIndex = content.indexOf("\"labels\": [") + "\"labels\": [".length val endIndex = content.indexOf("]", startIndex) val labelsStr = content.substring(startIndex, endIndex) // 处理引号 //val processedLabelsStr = labelsStr.replace("\"", "") val labels = labelsStr.split("\", \"") val processedLabels = mutableListOf() for (label in labels) { // 假设 label 是原始字符串 var processedLabel = label // 去掉单引号和双引号 if (label.contains("'")) { processedLabel = processedLabel.replace("'", "") } if (label.contains("\"")) { processedLabel = processedLabel.replace("\"", "") } // 去掉所有空格 processedLabel = processedLabel.replace(" ", "") processedLabels.add(processedLabel) } return processedLabels } } catch (e: Exception) { e.printStackTrace() Log.e("ExtractLabels", "Error during extraction: ${e.message}") } return null } class MainActivity : AppCompatActivity() { private lateinit var inputEditText: EditText private lateinit var configButton: Button private lateinit var submitToZhiPuAIButton: Button private lateinit var submitToSparkAIButton: Button private lateinit var tabLayout: TabLayout private lateinit var submitToServerButton: Button private lateinit var statusText: TextView @SuppressLint("MissingInflatedId", "CutPasteId", "SetTextI18n") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) inputEditText = findViewById(R.id.inputEditText) inputEditText.gravity = Gravity.START or Gravity.TOP // 状态栏目的信息 statusText = findViewById(R.id.statusTextView) submitToZhiPuAIButton = findViewById(R.id.submitToZhiPuAIButton) submitToZhiPuAIButton.setOnClickListener { // 创建 OkHttpClient,点击智谱AI分析返回标签 val client = OkHttpClient.Builder() .addInterceptor(Interceptor { chain -> val originalRequest = chain.request() val newRequest = originalRequest.newBuilder().build() chain.proceed(newRequest) }) .build() // 这是一个 EditText 元素 val inputEditText = findViewById(R.id.inputEditText) // 获取 EditText 中的文本内容,创建request的body val textFromEditText = inputEditText.text.toString() val combinedText = "$textFromEditText。请为以上文章分析并给出 4 个最合理的标签,没有其他内容。以 JSON 格式输出,格式为 labels: [标签 1, 标签 2, 标签 3, 标签 4]" // 从配置中读取 api_key val sharedPrefs = getSharedPreferences("APIConfigs", MODE_PRIVATE) val allConfigsJson = sharedPrefs.getString("configs", null) var apiKey = "" var apiUrl = "" var apiModel = "glm-4-flash" if (allConfigsJson != null) { val type = object : TypeToken>() {}.type val allConfigs = Gson().fromJson>(allConfigsJson, type) val zhipuConfig = allConfigs.find { it.name == "zhipu" } if (zhipuConfig != null) { apiKey = zhipuConfig.key apiUrl = zhipuConfig.url //apiModel = zhipuConfig.model statusText.text = "zhipuConfig配置文件$apiModel" } else { statusText.text = "没找到zhipuConfig配置文件" } } val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() val jsonAdapter = moshi.adapter(ChatRequest::class.java) val requestBody = ChatRequest( model = apiModel, messages = listOf(Message(role = "user", content = combinedText)) ) val requestBodyJson = jsonAdapter.toJson(requestBody) val mediaType = "application/json; charset=utf-8".toMediaType() val body = requestBodyJson.toRequestBody(mediaType) // 创建请求 val request = Request.Builder() .url(apiUrl) .post(body) .header("Authorization", "Bearer $apiKey") .header("Content-Type", "application/json") .build() // 使用协程在后台线程中发送请求 CoroutineScope(Dispatchers.Main).launch { try { // 模拟可能出现异常的网络操作,这里需要替换为你的实际网络请求相关代码 // 比如使用 OkHttp 或者其他网络库进行请求 val response = withContext(Dispatchers.IO) { statusText.text = "发起请求" client.newCall(request).execute() } if (response.isSuccessful) { statusText.text = "响应成功,等待标签解析" val responseBody = response.body?.string() // 将响应体转换为字符串 responseBody?.let { // 处理响应 JSON 数据 print("return message is $responseBody") val labels = extractLabels(responseBody) labels?.let { if (labels.size == 4) { for (i in 0 until 4) { val tab = tabLayout.getTabAt(i) if (tab != null) { tab.text = labels[i] tab.view.setOnClickListener { val currentText = findViewById(R.id.inputEditText).text.toString() val buttonText = tab.text.toString() inputEditText.setText("#$buttonText\n\n$currentText") statusText.text = "标签已增加" } } } statusText.text = "标签已经获取并更新" } } ?: run { statusText.text = "没有更新" } } } else { statusText.text = "没有响应,没有更新" } } catch (e: UnknownHostException) { statusText.text ="UnknownHostException: ${e.message}" } catch (e: IOException) { statusText.text = "IOException: ${e.message}" } } } submitToSparkAIButton = findViewById(R.id.submitToSparkAIButton) submitToSparkAIButton.setOnClickListener { // 创建 OkHttpClient,点击星火大模型分析返回标签 val client = OkHttpClient.Builder() .addInterceptor(Interceptor { chain -> val originalRequest = chain.request() val newRequest = originalRequest.newBuilder().build() chain.proceed(newRequest) }) .build() // 假设这是一个 EditText 元素 val inputEditText = findViewById(R.id.inputEditText) // 获取 EditText 中的文本内容,创建request的body val textFromEditText = inputEditText.text.toString() val combinedText = "$textFromEditText。如果是英文文章则先翻译成中文,并为以上文章分析并给出 4 个最合理的标签,没有其他内容。以 JSON 格式输出,格式为 labels: [标签 1, 标签 2, 标签 3, 标签 4]" // 从配置中读取 api_key val sharedPrefs = getSharedPreferences("APIConfigs", MODE_PRIVATE) val allConfigsJson = sharedPrefs.getString("configs", null) var apiKey = "" var apiUrl = "" var apiModel = "general" if (allConfigsJson != null) { val type = object : TypeToken>() {}.type val allConfigs = Gson().fromJson>(allConfigsJson, type) val sparkConfig = allConfigs.find { it.name == "spark" } if (sparkConfig != null) { apiKey = sparkConfig.key apiUrl = sparkConfig.url //apiModel = sparkConfig.model statusText.text = "sparkConfig配置文件$apiModel" } else { statusText.text = "没找到sparkConfig配置文件" } } // 配置 body的内容 val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() val jsonAdapter = moshi.adapter(ChatRequest::class.java) val requestBody = ChatRequest( model = apiModel, messages = listOf(Message(role = "user", content = combinedText)) ) val requestBodyJson = jsonAdapter.toJson(requestBody) val mediaType = "application/json; charset=utf-8".toMediaType() val body = requestBodyJson.toRequestBody(mediaType) // 创建请求 val request = Request.Builder() .url(apiUrl) .post(body) .header("Authorization", "Bearer $apiKey") .header("Content-Type", "application/json") .build() // 使用协程在后台线程中发送请求 CoroutineScope(Dispatchers.Main).launch { try { // 模拟可能出现异常的网络操作,这里需要替换为你的实际网络请求相关代码 // 比如使用 OkHttp 或者其他网络库进行请求 val response = withContext(Dispatchers.IO) { statusText.text = "提交请求" client.newCall(request).execute() } if (response.isSuccessful) { statusText.text = "响应成功,等待标签解析" val responseBody = response.body?.string() // 将响应体转换为字符串 responseBody?.let { // 处理响应 JSON 数据 val labels = extractLabels(responseBody) labels?.let { if (labels.size == 4) { for (i in 0 until 4) { val tab = tabLayout.getTabAt(i) if (tab != null) { tab.text = labels[i] tab.view.setOnClickListener { val currentText = findViewById(R.id.inputEditText).text.toString() val buttonText = tab.text.toString() inputEditText.setText("#$buttonText\n\n$currentText") statusText.text = "标签已增加" } } } statusText.text = "标签已经获取并更新" } } ?: run { statusText.text = "没有更新到标签" } } } else { statusText.text = "服务器没有响应,没有更新" } } catch (e: UnknownHostException) { statusText.text ="UnknownHostException: ${e.message}" } catch (e: IOException) { statusText.text = "IOException: ${e.message}" } } } tabLayout = findViewById(R.id.tabLayout) submitToServerButton = findViewById(R.id.submitToServerButton) // 点击配置按钮 configButton = findViewById(R.id.configButton) configButton.setOnClickListener { val intent = Intent(this, SecondActivity::class.java) startActivity(intent) } // 提交到flomo的服务器按钮 submitToServerButton = findViewById(R.id.submitToServerButton) inputEditText = findViewById(R.id.inputEditText) submitToServerButton.setOnClickListener { val textFromEditText = inputEditText.text.toString() submitToServer(textFromEditText) } // 创建4个按钮 val tabLayout = findViewById(R.id.tabLayout) // 维持原来的创建标签按钮的代码 (1..4).forEach { tabIndex -> tabLayout.newTab().apply { text = "标签示例$tabIndex" tabLayout.addTab(this) } } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == SecondActivity.REQUEST_CODE_PICK_IMAGE && resultCode == Activity.RESULT_OK && data != null) { val selectedImageUri = data.getStringExtra("selectedImageUri") if (selectedImageUri != null) { val imageView = findViewById(R.id.imageViewBackground) // 假设你的背景是一个ImageView imageView.setImageURI(Uri.parse(selectedImageUri)) } } } override fun onStart() { super.onStart() // 获取从其他 Activity 传递过来的按钮颜色值,如果没有传递颜色值,则默认值为透明色。 val statusTextView = findViewById(R.id.statusTextView) updateStatusTextViewColor(statusTextView) } private fun updateStatusTextViewColor(statusTextView: TextView) { try { val sharedPrefs = getSharedPreferences("APIConfigs", Context.MODE_PRIVATE) val colorValue = sharedPrefs.getString("buttonColor", "") Log.d("SharedPrefsDebug", "读取颜色值 MainActivity: $colorValue") if (colorValue.isNullOrEmpty()) { statusTextView.setBackgroundResource(android.R.color.holo_blue_dark) } else { // 根据提取的颜色值设置背景颜色,这里只是一个示例,实际应用中可能需要更复杂的逻辑 when (colorValue) { "red" -> statusTextView.setBackgroundResource(android.R.color.holo_red_light) "green" -> statusTextView.setBackgroundResource(android.R.color.holo_green_light) "blue" -> statusTextView.setBackgroundResource(android.R.color.holo_blue_light) "orange" -> statusTextView.setBackgroundResource(android.R.color.holo_orange_light) else -> { // 如果颜色值不在预定义的列表中,使用默认颜色 statusTextView.setBackgroundResource(android.R.color.holo_blue_dark) Log.e("SharedPrefsError", "Invalid color value: $colorValue") } } } } catch (e: Exception) { // 捕获并记录任何异常 Log.e("SharedPrefsError", "更新状态文本视图颜色时出错\n: ${e.message}", e) // 设置默认颜色 statusTextView.setBackgroundResource(android.R.color.holo_blue_dark) } } private fun getBitmapFromUri(uri: Uri): Bitmap? { val inputStream: InputStream? = contentResolver.openInputStream(uri) return BitmapFactory.decodeStream(inputStream) } @SuppressLint("SetTextI18n") private fun submitToServer(content: String) { CoroutineScope(Dispatchers.Main).launch { statusText.text = "提交到flomo服务器..." val result = withContext(Dispatchers.IO) { postDataToServer(content) } when (result) { is Result.Success -> { findViewById(R.id.inputEditText).setText("") statusText.text = "提交成功!" } is Result.Error -> { statusText.text = "提交失误: ${result.exception.message}" } } } } // 提交到笔记服务器,flomo服务器 private fun postDataToServer(content: String): Result { return try { val client = OkHttpClient() val mediaType = "application/json".toMediaType() val json = JSONObject().apply { put("content", content) }.toString() val body = json.toRequestBody(mediaType) val request = Request.Builder() .url("https://flomoapp.com/iwh/MTY5NTQy/b671d4930ecd1eae63e50cc0cb8ca4ae/") .post(body) .build() val response = client.newCall(request).execute() if (response.isSuccessful) { Result.Success(response) } else { Result.Error(Exception("服务器返回错误: ${response.code}")) } } catch (e: Exception) { Result.Error(e) } } sealed class Result { data class Success(val response: Response) : Result() data class Error(val exception: Exception) : Result() } }