mm
1
androidExampleDemo/app/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/build
|
||||
@@ -1,113 +0,0 @@
|
||||
plugins {
|
||||
<<<<<<< HEAD
|
||||
id 'com.android.application'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.example.agentclient'
|
||||
compileSdk 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example.agentclient"
|
||||
minSdk 24
|
||||
=======
|
||||
alias(libs.plugins.android.application)
|
||||
id 'dagger.hilt.android.plugin'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.example.demo'
|
||||
compileSdk 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example.demo"
|
||||
minSdk 26
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
targetSdk 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
=======
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
<<<<<<< HEAD
|
||||
// Android Core
|
||||
implementation 'androidx.core:core:1.12.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.10.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime:2.6.2'
|
||||
implementation 'androidx.activity:activity:1.8.1'
|
||||
|
||||
// Retrofit & OkHttp
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
|
||||
|
||||
// Gson
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
|
||||
// Testing
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
}
|
||||
=======
|
||||
// 基础Android库
|
||||
implementation libs.appcompat
|
||||
implementation libs.material
|
||||
|
||||
// 生命周期和ViewModel
|
||||
implementation libs.lifecycle.viewmodel
|
||||
implementation libs.lifecycle.livedata
|
||||
|
||||
// Room数据库
|
||||
implementation libs.room.runtime
|
||||
annotationProcessor libs.room.compiler
|
||||
|
||||
// 网络库
|
||||
implementation libs.retrofit
|
||||
implementation libs.retrofit.gson
|
||||
implementation libs.okhttp.logging
|
||||
|
||||
// 依赖注入
|
||||
implementation libs.hilt.android
|
||||
annotationProcessor libs.hilt.compiler
|
||||
|
||||
// 工作管理器
|
||||
implementation libs.work.runtime
|
||||
|
||||
// 蓝牙库
|
||||
implementation libs.ble
|
||||
|
||||
// 测试库
|
||||
testImplementation libs.junit
|
||||
androidTestImplementation libs.ext.junit
|
||||
androidTestImplementation libs.espresso.core
|
||||
}
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
54
androidExampleDemo/app/proguard-rules.pro
vendored
@@ -1,54 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
<<<<<<< HEAD
|
||||
|
||||
# Retrofit
|
||||
-keepattributes Signature, InnerClasses, EnclosingMethod
|
||||
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
|
||||
-keepclassmembers,allowshrinking,allowobfuscation interface * {
|
||||
@retrofit2.http.* <methods>;
|
||||
}
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||
-dontwarn javax.annotation.**
|
||||
-dontwarn kotlin.Unit
|
||||
-dontwarn retrofit2.KotlinExtensions
|
||||
-dontwarn retrofit2.KotlinExtensions$*
|
||||
|
||||
# OkHttp
|
||||
-dontwarn okhttp3.**
|
||||
-dontwarn okio.**
|
||||
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
|
||||
|
||||
# Gson
|
||||
-keepattributes Signature
|
||||
-keepattributes *Annotation*
|
||||
-dontwarn sun.misc.**
|
||||
-keep class com.google.gson.** { *; }
|
||||
-keep class * implements com.google.gson.TypeAdapter
|
||||
-keep class * implements com.google.gson.TypeAdapterFactory
|
||||
-keep class * implements com.google.gson.JsonSerializer
|
||||
-keep class * implements com.google.gson.JsonDeserializer
|
||||
|
||||
# Keep model classes
|
||||
-keep class com.example.agentclient.models.** { *; }
|
||||
=======
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.example.obd;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("com.example.obd", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<<<<<<< HEAD
|
||||
<!-- 网络权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
=======
|
||||
<!-- OBD应用所需权限 -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<!-- 针对Android 12+ -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
<<<<<<< HEAD
|
||||
android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
=======
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
tools:targetApi="31">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".DeviceDiscoveryActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
@@ -1,430 +0,0 @@
|
||||
package com.example.agentclient;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.example.agentclient.models.*;
|
||||
import com.example.agentclient.utils.ApiClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* 主Activity - 调用情感分析Agent示例
|
||||
*
|
||||
* 功能:
|
||||
* 1. 自动登录
|
||||
* 2. 通过Agent名称查找Agent ID
|
||||
* 3. 发送文本进行情感分析
|
||||
* 4. 轮询获取执行结果
|
||||
*/
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
// TODO: 修改为你的配置
|
||||
private static final String USERNAME = "admin";
|
||||
private static final String PASSWORD = "123456";
|
||||
private static final String AGENT_NAME = "情感分析Agent"; // Agent名称
|
||||
|
||||
private TextView tvStatus;
|
||||
private TextView tvMessages;
|
||||
private EditText etInput;
|
||||
private Button btnSend;
|
||||
private ProgressBar progressBar;
|
||||
private ScrollView scrollView;
|
||||
|
||||
private String accessToken;
|
||||
private String agentId;
|
||||
private Handler mainHandler;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
initViews();
|
||||
mainHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
// 启动时自动登录
|
||||
login();
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
tvStatus = findViewById(R.id.tvStatus);
|
||||
tvMessages = findViewById(R.id.tvMessages);
|
||||
etInput = findViewById(R.id.etInput);
|
||||
btnSend = findViewById(R.id.btnSend);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
scrollView = findViewById(R.id.scrollView);
|
||||
|
||||
btnSend.setOnClickListener(v -> {
|
||||
String input = etInput.getText().toString().trim();
|
||||
if (input.isEmpty()) {
|
||||
Toast.makeText(this, "请输入要分析的文本", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
sendMessage(input);
|
||||
});
|
||||
|
||||
updateStatus("准备登录...");
|
||||
addMessage("系统", "正在连接服务器...");
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
private void login() {
|
||||
updateStatus("正在登录...");
|
||||
addMessage("系统", "正在登录...");
|
||||
|
||||
ApiClient.getService().login(USERNAME, PASSWORD).enqueue(new Callback<TokenResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<TokenResponse> call, Response<TokenResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
accessToken = "Bearer " + response.body().getAccessToken();
|
||||
updateStatus("登录成功");
|
||||
addMessage("系统", "登录成功!正在查找Agent...");
|
||||
|
||||
// 登录成功后查找Agent
|
||||
findAgentByName(AGENT_NAME);
|
||||
} else {
|
||||
String errorMsg = "登录失败: " + response.code();
|
||||
try {
|
||||
if (response.errorBody() != null) {
|
||||
errorMsg += "\n" + response.errorBody().string();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
updateStatus("登录失败");
|
||||
addMessage("系统", errorMsg);
|
||||
Toast.makeText(MainActivity.this, errorMsg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<TokenResponse> call, Throwable t) {
|
||||
String errorMsg = "登录失败: " + t.getMessage();
|
||||
updateStatus("登录失败");
|
||||
addMessage("系统", errorMsg);
|
||||
Toast.makeText(MainActivity.this, errorMsg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过名称查找Agent
|
||||
*/
|
||||
private void findAgentByName(String agentName) {
|
||||
updateStatus("正在查找Agent: " + agentName);
|
||||
|
||||
ApiClient.getService().getAgents(agentName, 100, accessToken)
|
||||
.enqueue(new Callback<List<Agent>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<Agent>> call, Response<List<Agent>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
List<Agent> agents = response.body();
|
||||
|
||||
// 精确匹配名称
|
||||
Agent foundAgent = null;
|
||||
for (Agent agent : agents) {
|
||||
if (agentName.equals(agent.getName())) {
|
||||
foundAgent = agent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundAgent != null) {
|
||||
agentId = foundAgent.getId();
|
||||
String status = foundAgent.getStatus();
|
||||
updateStatus("已找到Agent: " + agentName);
|
||||
addMessage("系统", String.format(
|
||||
"找到Agent: %s\nID: %s\n状态: %s",
|
||||
foundAgent.getName(),
|
||||
agentId,
|
||||
status
|
||||
));
|
||||
|
||||
if (!"published".equals(status) && !"running".equals(status)) {
|
||||
addMessage("系统", "警告: Agent状态为 '" + status + "',可能无法执行");
|
||||
}
|
||||
|
||||
addMessage("系统", "可以开始发送文本进行情感分析了!");
|
||||
} else {
|
||||
updateStatus("未找到Agent");
|
||||
addMessage("系统", "未找到名称为 '" + agentName + "' 的Agent");
|
||||
if (!agents.isEmpty()) {
|
||||
addMessage("系统", "找到以下相似的Agent:");
|
||||
for (int i = 0; i < Math.min(5, agents.size()); i++) {
|
||||
Agent agent = agents.get(i);
|
||||
addMessage("系统", String.format(
|
||||
" - %s (ID: %s, 状态: %s)",
|
||||
agent.getName(),
|
||||
agent.getId(),
|
||||
agent.getStatus()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String errorMsg = "查找Agent失败: " + response.code();
|
||||
updateStatus("查找Agent失败");
|
||||
addMessage("系统", errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<Agent>> call, Throwable t) {
|
||||
String errorMsg = "查找Agent失败: " + t.getMessage();
|
||||
updateStatus("查找Agent失败");
|
||||
addMessage("系统", errorMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息到Agent
|
||||
*/
|
||||
private void sendMessage(String userInput) {
|
||||
if (agentId == null || agentId.isEmpty()) {
|
||||
Toast.makeText(this, "Agent未找到,请先查找Agent", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (accessToken == null || accessToken.isEmpty()) {
|
||||
Toast.makeText(this, "未登录,请先登录", Toast.LENGTH_SHORT).show();
|
||||
login();
|
||||
return;
|
||||
}
|
||||
|
||||
// 禁用发送按钮
|
||||
btnSend.setEnabled(false);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
|
||||
// 显示用户输入
|
||||
addMessage("我", userInput);
|
||||
updateStatus("正在发送请求...");
|
||||
|
||||
// 构建请求数据
|
||||
Map<String, Object> inputData = new HashMap<>();
|
||||
inputData.put("query", userInput);
|
||||
inputData.put("USER_INPUT", userInput);
|
||||
|
||||
AgentExecutionRequest request = new AgentExecutionRequest(agentId, inputData);
|
||||
|
||||
// 执行Agent
|
||||
ApiClient.getService().executeAgent(request, accessToken)
|
||||
.enqueue(new Callback<ExecutionResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<ExecutionResponse> call, Response<ExecutionResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
ExecutionResponse execution = response.body();
|
||||
String executionId = execution.getId();
|
||||
updateStatus("请求已发送,执行ID: " + executionId);
|
||||
addMessage("系统", "正在处理,请稍候...");
|
||||
|
||||
// 轮询获取结果
|
||||
pollExecutionResult(executionId);
|
||||
} else {
|
||||
String errorMsg = "执行失败: " + response.code();
|
||||
try {
|
||||
if (response.errorBody() != null) {
|
||||
errorMsg += "\n" + response.errorBody().string();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
updateStatus("执行失败");
|
||||
addMessage("系统", errorMsg);
|
||||
btnSend.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ExecutionResponse> call, Throwable t) {
|
||||
String errorMsg = "执行失败: " + t.getMessage();
|
||||
updateStatus("执行失败");
|
||||
addMessage("系统", errorMsg);
|
||||
btnSend.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 轮询获取执行结果
|
||||
*/
|
||||
private void pollExecutionResult(String executionId) {
|
||||
ApiClient.getService().getExecutionStatus(executionId, accessToken)
|
||||
.enqueue(new Callback<ExecutionStatusResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<ExecutionStatusResponse> call, Response<ExecutionStatusResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
ExecutionStatusResponse statusResponse = response.body();
|
||||
String status = statusResponse.getStatus();
|
||||
|
||||
// 显示当前节点信息
|
||||
if (statusResponse.getCurrentNode() != null) {
|
||||
ExecutionStatusResponse.CurrentNode node = statusResponse.getCurrentNode();
|
||||
updateStatus(String.format("执行中: %s (%s)",
|
||||
node.getNodeName() != null ? node.getNodeName() : node.getNodeId(),
|
||||
node.getNodeType()));
|
||||
}
|
||||
|
||||
if ("completed".equals(status)) {
|
||||
// 执行完成,获取结果
|
||||
getExecutionResult(executionId);
|
||||
} else if ("failed".equals(status) || "error".equals(status)) {
|
||||
// 执行失败
|
||||
String errorMsg = statusResponse.getError();
|
||||
if (errorMsg == null || errorMsg.isEmpty()) {
|
||||
errorMsg = "执行失败";
|
||||
}
|
||||
updateStatus("执行失败");
|
||||
addMessage("系统", "执行失败: " + errorMsg);
|
||||
btnSend.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
} else {
|
||||
// 继续轮询
|
||||
mainHandler.postDelayed(() -> pollExecutionResult(executionId), 1000);
|
||||
}
|
||||
} else {
|
||||
// 继续轮询
|
||||
mainHandler.postDelayed(() -> pollExecutionResult(executionId), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ExecutionStatusResponse> call, Throwable t) {
|
||||
// 继续轮询
|
||||
mainHandler.postDelayed(() -> pollExecutionResult(executionId), 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取执行结果
|
||||
*/
|
||||
private void getExecutionResult(String executionId) {
|
||||
ApiClient.getService().getExecutionResult(executionId, accessToken)
|
||||
.enqueue(new Callback<ExecutionResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<ExecutionResponse> call, Response<ExecutionResponse> response) {
|
||||
btnSend.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
ExecutionResponse execution = response.body();
|
||||
Object outputData = execution.getOutputData();
|
||||
|
||||
updateStatus("执行完成");
|
||||
|
||||
// 格式化输出
|
||||
String result = formatOutput(outputData);
|
||||
addMessage("Agent", result);
|
||||
} else {
|
||||
String errorMsg = "获取结果失败: " + response.code();
|
||||
updateStatus("获取结果失败");
|
||||
addMessage("系统", errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ExecutionResponse> call, Throwable t) {
|
||||
btnSend.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
String errorMsg = "获取结果失败: " + t.getMessage();
|
||||
updateStatus("获取结果失败");
|
||||
addMessage("系统", errorMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化输出数据
|
||||
*/
|
||||
private String formatOutput(Object outputData) {
|
||||
if (outputData == null) {
|
||||
return "无输出";
|
||||
}
|
||||
|
||||
if (outputData instanceof String) {
|
||||
return (String) outputData;
|
||||
}
|
||||
|
||||
if (outputData instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) outputData;
|
||||
|
||||
// 优先提取output字段
|
||||
if (map.containsKey("output") && map.get("output") instanceof String) {
|
||||
return (String) map.get("output");
|
||||
}
|
||||
|
||||
// 如果只有一个key,直接返回其值
|
||||
if (map.size() == 1) {
|
||||
Object value = map.values().iterator().next();
|
||||
if (value instanceof String) {
|
||||
return (String) value;
|
||||
}
|
||||
}
|
||||
|
||||
// 否则转换为字符串
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
if (!entry.getKey().startsWith("_")) {
|
||||
sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
|
||||
}
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
return outputData.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态栏
|
||||
*/
|
||||
private void updateStatus(String status) {
|
||||
mainHandler.post(() -> {
|
||||
if (tvStatus != null) {
|
||||
tvStatus.setText("状态: " + status);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加消息到消息列表
|
||||
*/
|
||||
private void addMessage(String sender, String message) {
|
||||
mainHandler.post(() -> {
|
||||
if (tvMessages != null) {
|
||||
String currentText = tvMessages.getText().toString();
|
||||
String newMessage = String.format("[%s] %s\n\n", sender, message);
|
||||
tvMessages.append(newMessage);
|
||||
|
||||
// 自动滚动到底部
|
||||
if (scrollView != null) {
|
||||
scrollView.post(() -> scrollView.fullScroll(View.FOCUS_DOWN));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.example.agentclient.models;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Agent模型
|
||||
*/
|
||||
public class Agent {
|
||||
private String id;
|
||||
private String name;
|
||||
private String description;
|
||||
private String status;
|
||||
|
||||
@SerializedName("created_at")
|
||||
private String createdAt;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(String createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.example.agentclient.models;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Agent执行请求模型
|
||||
*/
|
||||
public class AgentExecutionRequest {
|
||||
@SerializedName("agent_id")
|
||||
private String agentId;
|
||||
|
||||
@SerializedName("input_data")
|
||||
private Map<String, Object> inputData;
|
||||
|
||||
public AgentExecutionRequest(String agentId, Map<String, Object> inputData) {
|
||||
this.agentId = agentId;
|
||||
this.inputData = inputData;
|
||||
}
|
||||
|
||||
public String getAgentId() {
|
||||
return agentId;
|
||||
}
|
||||
|
||||
public void setAgentId(String agentId) {
|
||||
this.agentId = agentId;
|
||||
}
|
||||
|
||||
public Map<String, Object> getInputData() {
|
||||
return inputData;
|
||||
}
|
||||
|
||||
public void setInputData(Map<String, Object> inputData) {
|
||||
this.inputData = inputData;
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package com.example.agentclient.models;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 执行记录响应模型
|
||||
*/
|
||||
public class ExecutionResponse {
|
||||
private String id;
|
||||
|
||||
@SerializedName("agent_id")
|
||||
private String agentId;
|
||||
|
||||
@SerializedName("workflow_id")
|
||||
private String workflowId;
|
||||
|
||||
private String status;
|
||||
|
||||
@SerializedName("input_data")
|
||||
private Map<String, Object> inputData;
|
||||
|
||||
@SerializedName("output_data")
|
||||
private Object outputData;
|
||||
|
||||
@SerializedName("created_at")
|
||||
private String createdAt;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAgentId() {
|
||||
return agentId;
|
||||
}
|
||||
|
||||
public void setAgentId(String agentId) {
|
||||
this.agentId = agentId;
|
||||
}
|
||||
|
||||
public String getWorkflowId() {
|
||||
return workflowId;
|
||||
}
|
||||
|
||||
public void setWorkflowId(String workflowId) {
|
||||
this.workflowId = workflowId;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Map<String, Object> getInputData() {
|
||||
return inputData;
|
||||
}
|
||||
|
||||
public void setInputData(Map<String, Object> inputData) {
|
||||
this.inputData = inputData;
|
||||
}
|
||||
|
||||
public Object getOutputData() {
|
||||
return outputData;
|
||||
}
|
||||
|
||||
public void setOutputData(Object outputData) {
|
||||
this.outputData = outputData;
|
||||
}
|
||||
|
||||
public String getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(String createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package com.example.agentclient.models;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* 执行状态响应模型
|
||||
*/
|
||||
public class ExecutionStatusResponse {
|
||||
private String status;
|
||||
private int progress = 0;
|
||||
|
||||
@SerializedName("current_node")
|
||||
private CurrentNode currentNode;
|
||||
|
||||
private String error;
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setProgress(int progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public CurrentNode getCurrentNode() {
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
public void setCurrentNode(CurrentNode currentNode) {
|
||||
this.currentNode = currentNode;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前执行节点
|
||||
*/
|
||||
public static class CurrentNode {
|
||||
@SerializedName("node_id")
|
||||
private String nodeId;
|
||||
|
||||
@SerializedName("node_name")
|
||||
private String nodeName;
|
||||
|
||||
@SerializedName("node_type")
|
||||
private String nodeType;
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public void setNodeId(String nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
}
|
||||
|
||||
public String getNodeName() {
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
public void setNodeName(String nodeName) {
|
||||
this.nodeName = nodeName;
|
||||
}
|
||||
|
||||
public String getNodeType() {
|
||||
return nodeType;
|
||||
}
|
||||
|
||||
public void setNodeType(String nodeType) {
|
||||
this.nodeType = nodeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.example.agentclient.models;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Token响应模型
|
||||
*/
|
||||
public class TokenResponse {
|
||||
@SerializedName("access_token")
|
||||
private String accessToken;
|
||||
|
||||
@SerializedName("token_type")
|
||||
private String tokenType = "bearer";
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
package com.example.agentclient.utils;
|
||||
|
||||
import com.example.agentclient.models.*;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import retrofit2.http.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* API客户端配置
|
||||
*
|
||||
* 使用说明:
|
||||
* 1. 修改 BASE_URL 为你的服务器地址
|
||||
* 2. 确保服务器允许跨域请求(CORS)
|
||||
*/
|
||||
public class ApiClient {
|
||||
// TODO: 修改为你的服务器地址
|
||||
private static final String BASE_URL = "http://101.43.95.130:8037";
|
||||
|
||||
private static Retrofit retrofit;
|
||||
private static AgentService agentService;
|
||||
|
||||
static {
|
||||
// 创建OkHttp客户端
|
||||
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
|
||||
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
|
||||
OkHttpClient okHttpClient = new OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.writeTimeout(60, TimeUnit.SECONDS)
|
||||
.addInterceptor(logging)
|
||||
.build();
|
||||
|
||||
// 创建Retrofit实例
|
||||
retrofit = new Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(okHttpClient)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build();
|
||||
|
||||
// 创建API服务
|
||||
agentService = retrofit.create(AgentService.class);
|
||||
}
|
||||
|
||||
public static AgentService getService() {
|
||||
return agentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent API接口
|
||||
*/
|
||||
public interface AgentService {
|
||||
/**
|
||||
* 用户登录
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @return Token响应
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/auth/login")
|
||||
retrofit2.Call<TokenResponse> login(
|
||||
@Field("username") String username,
|
||||
@Field("password") String password
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取Agent列表(支持搜索)
|
||||
*
|
||||
* @param search 搜索关键词(Agent名称)
|
||||
* @param limit 返回数量限制
|
||||
* @param token 认证Token
|
||||
* @return Agent列表
|
||||
*/
|
||||
@GET("/api/v1/agents")
|
||||
retrofit2.Call<List<Agent>> getAgents(
|
||||
@Query("search") String search,
|
||||
@Query("limit") Integer limit,
|
||||
@Header("Authorization") String token
|
||||
);
|
||||
|
||||
/**
|
||||
* 执行Agent
|
||||
*
|
||||
* @param request Agent执行请求
|
||||
* @param token 认证Token
|
||||
* @return 执行记录
|
||||
*/
|
||||
@POST("/api/v1/executions")
|
||||
retrofit2.Call<ExecutionResponse> executeAgent(
|
||||
@Body AgentExecutionRequest request,
|
||||
@Header("Authorization") String token
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取执行状态
|
||||
*
|
||||
* @param executionId 执行ID
|
||||
* @param token 认证Token
|
||||
* @return 执行状态
|
||||
*/
|
||||
@GET("/api/v1/executions/{execution_id}/status")
|
||||
retrofit2.Call<ExecutionStatusResponse> getExecutionStatus(
|
||||
@Path("execution_id") String executionId,
|
||||
@Header("Authorization") String token
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取执行结果
|
||||
*
|
||||
* @param executionId 执行ID
|
||||
* @param token 认证Token
|
||||
* @return 执行详情
|
||||
*/
|
||||
@GET("/api/v1/executions/{execution_id}")
|
||||
retrofit2.Call<ExecutionResponse> getExecutionResult(
|
||||
@Path("execution_id") String executionId,
|
||||
@Header("Authorization") String token
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.example.demo;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<corners android:radius="8dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/primary_color" />
|
||||
</shape>
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/primary_color" />
|
||||
<corners android:radius="8dp" />
|
||||
<stroke
|
||||
android:width="0dp"
|
||||
android:color="@color/primary_color" />
|
||||
</shape>
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/accent_color" />
|
||||
<corners android:radius="8dp" />
|
||||
<stroke
|
||||
android:width="0dp"
|
||||
android:color="@color/accent_color" />
|
||||
</shape>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="12dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/divider_color" />
|
||||
<padding
|
||||
android:left="16dp"
|
||||
android:top="16dp"
|
||||
android:right="16dp"
|
||||
android:bottom="16dp" />
|
||||
</shape>
|
||||
@@ -1,170 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
@@ -1,30 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
@@ -1,94 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="@color/background_color">
|
||||
|
||||
<!-- 标题 -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发现OBD设备"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_text"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- 状态信息 -->
|
||||
<TextView
|
||||
android:id="@+id/status_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="点击扫描按钮开始搜索OBD设备"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/secondary_text"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- 扫描控制按钮 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_scan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_weight="1"
|
||||
android:text="开始扫描"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@android:color/white"
|
||||
android:background="@drawable/button_primary"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:elevation="4dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_stop_scan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_weight="1"
|
||||
android:text="停止扫描"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@android:color/white"
|
||||
android:background="@drawable/button_secondary"
|
||||
android:layout_marginStart="8dp"
|
||||
android:elevation="4dp"
|
||||
android:enabled="false" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 设备列表 -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发现的设备:"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_text"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<ListView
|
||||
android:id="@+id/device_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/data_card_background"
|
||||
android:divider="@color/divider_color"
|
||||
android:dividerHeight="1dp"
|
||||
android:padding="8dp" />
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="点击设备名称进行连接"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/secondary_text"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,85 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<<<<<<< HEAD
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 状态栏 -->
|
||||
<TextView
|
||||
android:id="@+id/tvStatus"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="状态: 准备中..."
|
||||
android:textSize="14sp"
|
||||
android:textColor="#666666"
|
||||
android:padding="8dp"
|
||||
android:background="#F5F5F5"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<!-- 消息显示区域 -->
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#FFFFFF"
|
||||
android:padding="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvMessages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#333333"
|
||||
android:lineSpacingExtra="4dp" />
|
||||
</ScrollView>
|
||||
|
||||
<!-- 进度条 -->
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 输入区域 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etInput"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="请输入要分析的文本..."
|
||||
android:minHeight="48dp"
|
||||
android:padding="12dp"
|
||||
android:background="@android:drawable/edit_text"
|
||||
android:maxLines="5"
|
||||
android:gravity="top|start" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnSend"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发送"
|
||||
android:layout_marginStart="8dp"
|
||||
android:minWidth="80dp"
|
||||
android:minHeight="48dp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
=======
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 982 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 184 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 924 B |
|
Before Width: | Height: | Size: 351 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 570 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 389 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- 系统基础颜色 -->
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
|
||||
<!-- 应用自定义颜色 -->
|
||||
<color name="primary_color">#2196F3</color>
|
||||
<color name="primary_dark">#1976D2</color>
|
||||
<color name="accent_color">#FF4081</color>
|
||||
<color name="background_color">#F5F5F5</color>
|
||||
<color name="primary_text">#212121</color>
|
||||
<color name="secondary_text">#757575</color>
|
||||
<color name="divider_color">#BDBDBD</color>
|
||||
</resources>
|
||||
@@ -1,33 +0,0 @@
|
||||
<<<<<<< HEAD
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Agent客户端</string>
|
||||
</resources>
|
||||
=======
|
||||
<resources>
|
||||
<string name="app_name">个人知库</string>
|
||||
<string name="welcome_message">欢迎使用OBD诊断工具</string>
|
||||
<string name="connect_bluetooth">连接蓝牙OBD设备</string>
|
||||
<string name="connect_wifi">连接WiFi OBD</string>
|
||||
<string name="settings">设置</string>
|
||||
<string name="ready_status">准备就绪</string>
|
||||
<string name="permission_bluetooth_required">需要蓝牙权限才能连接OBD设备</string>
|
||||
<string name="permission_location_required">需要位置权限才能扫描蓝牙设备</string>
|
||||
<string name="bluetooth_not_available">设备不支持蓝牙</string>
|
||||
<string name="bluetooth_disabled">蓝牙未启用</string>
|
||||
<string name="scanning_devices">正在搜索OBD设备...</string>
|
||||
|
||||
<!-- 数据采集相关 -->
|
||||
<string name="start_collection">开始采集</string>
|
||||
<string name="stop_collection">停止采集</string>
|
||||
<string name="upload_data">上传数据</string>
|
||||
<string name="view_history">查看历史</string>
|
||||
<string name="collection_running">采集中...</string>
|
||||
<string name="collection_stopped">已停止</string>
|
||||
<string name="collection_paused">已暂停</string>
|
||||
<string name="data_uploaded">数据已上传</string>
|
||||
<string name="upload_failed">上传失败</string>
|
||||
<string name="no_data_to_upload">没有数据需要上传</string>
|
||||
<string name="bluetooth_settings_instruction">请在系统蓝牙设置中搜索并连接您的OBD设备,然后返回应用</string>
|
||||
</resources>
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
@@ -1,16 +0,0 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Obd" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<<<<<<< HEAD
|
||||
<!-- 允许HTTP连接(仅用于开发,生产环境应使用HTTPS) -->
|
||||
=======
|
||||
<!-- 允许所有 HTTP 流量 -->
|
||||
>>>>>>> 7c5f94d47066e9f9fb4cd23e74fe34d53d326684
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.example.obd;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||