10 Commits
1.0.1 ... 1.0.3

Author SHA1 Message Date
Zhanghu
80341f540f 当选择自动跳转时,直接访问 URL 前缀,这样网址自由设置 2025-11-01 10:03:36 +08:00
Zhanghu
cb151b989e fix retry count 2025-10-31 17:32:58 +08:00
Zhanghu
d450cf4933 changelog 2025-10-11 17:12:39 +08:00
Zhanghu
d4f3340383 小改动 2025-10-11 09:47:04 +08:00
Zhanghu
bdb20c2130 changelog 2025-10-11 08:45:08 +08:00
Zhanghu
605e482199 翻译 2025-10-10 16:11:34 +08:00
Zhanghu
3aa55dd875 小改动 2025-10-10 16:09:06 +08:00
Zhanghu
31a82e5461 优化图标和翻译 2025-10-10 16:05:25 +08:00
Zhanghu
4551fe1f5a * 设置界面支持切换到不同类型的仪表盘地址,默认是自动跳转
* 监听遥控器 F8 按键,打开设置界面
* webView 禁止缩放,避免受到安卓字体和dpi缩放的影响
2025-10-10 15:42:24 +08:00
Zhanghu
80a8226c80 readme 2025-09-16 16:58:40 +08:00
25 changed files with 197 additions and 243 deletions

View File

@@ -51,14 +51,14 @@ android {
}
android.applicationVariants.all { variant ->
def docDir = rootProject.getRootDir().getAbsolutePath() + "/../apk/dashboard"
def releaseDir = rootProject.getRootDir().getAbsolutePath() + "/../apk/dashboard"
def docDir = rootProject.getRootDir().getAbsolutePath() + "/../apk/dashboardclient"
def releaseDir = rootProject.getRootDir().getAbsolutePath() + "/../apk/dashboardclient"
if (versionName.contains("beta"))
releaseDir += "/beta"
variant.outputs.all {
// 常规版本不加后缀
outputFileName = "dashboard_${defaultConfig.versionName}.apk"
outputFileName = "dashboardclient_${defaultConfig.versionName}.apk"
}
// assemble 结束后将apk复制到指定目录
@@ -70,7 +70,7 @@ android {
into releaseDir
}
def downloadUrl = "http://thinkdisk.thinkbo.cn/src/web/dashboard/${outputFileName}"
def downloadUrl = "http://thinkdisk.thinkbo.cn/src/web/dashboardclient/${outputFileName}"
genUpdateJson(downloadUrl, releaseDir, outputFileName, 'changelog.md', defaultConfig, variant)
File file = new File("${project.getProjectDir().path}/changelog.md")

View File

@@ -1,5 +1,5 @@
---
title: "看板APP更新日志和文件下载"
title: "仪表盘 APP 更新日志和文件下载"
author:
- 宁波升维信息技术有限公司
---
@@ -9,11 +9,32 @@ author:
2. $ {VERSION_CODE} (去掉空格),会自动替换实际修订号,比如 1.1.4.$ {VERSION_CODE}
-->
### [1.0.1.${VERSION_CODE}] - 2025.9.16
### [1.0.3.${VERSION_CODE}] - 2025.11.1
#### 文件下载
* [dashboard_1.0.1.apk](dashboard_1.0.1.apk)
* [dashboardclient_1.0.3.apk](dashboardclient_1.0.3.apk)
#### 更新记录
* 当选择自动跳转时,直接访问 URL 前缀,这样网址自由设置
### [1.0.2.19] - 2025.10.11
#### 文件下载
* [dashboardclient_1.0.2.apk](dashboardclient_1.0.2.apk)
#### 更新记录
* 设置界面支持切换到不同类型的仪表盘地址,默认是自动跳转
* 监听遥控器 F8 按键,打开设置界面
* webView 禁止缩放避免受到安卓字体和dpi缩放的影响
* 优化图标和翻译
### [1.0.1.12] - 2025.9.16
#### 文件下载
* [dashboardclient_1.0.1.apk](dashboardclient_1.0.1.apk)
#### 更新记录
* APP 启动时,发送一次电视开机指令
@@ -22,7 +43,7 @@ author:
#### 文件下载
* [dashboard_1.0.0.apk](dashboard_1.0.0.apk)
* [dashboardclient_1.0.0.apk](dashboard_1.0.0.apk)
#### 更新记录
* 初版

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -5,12 +5,14 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebResourceError;
@@ -94,16 +96,19 @@ public class BuildingDashboardActivity extends FullscreenActivity {
protected void onResume() {
super.onResume();
// 当用户选择了自动跳转时,直接访问 urlPrefix这样 url 可以自由设置
SharedPreferences pre = PreferenceManager.getDefaultSharedPreferences(this);
String url = pre.getString("k_url", "http://172.18.22.211:8002/Dashboard");
mainUrl = url + "/index.html";
configUrl = url + "/data/config.json";
String urlPrefix = pre.getString("k_url_prefix", "http://172.18.22.211:8002/Dashboard");
String urlEndPoint = pre.getString("k_url_end_point", "/").replaceFirst("^/", "");
configUrl = urlPrefix + "/data/config.json";
mainUrl = urlEndPoint.isEmpty() ? urlPrefix : urlPrefix + "/" + urlEndPoint;
configLoadHandler.post(configLoadRunnable);
loadUrlWithRetry();
}
private void loadUrlWithRetry() {
Log.i("WebView", "Loading " + mainUrl);
binding.webview.loadUrl(mainUrl);
}
@@ -142,6 +147,24 @@ public class BuildingDashboardActivity extends FullscreenActivity {
}
}
/**
* 监听按键,因为 WebView 可能会拦截功能键,这里不使用 onKeyDown
* @param event
* @return
*/
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
Log.d(TAG, "dispatchKeyEvent:" + event.getKeyCode());
if ( event.getKeyCode() == KeyEvent.KEYCODE_F8
&& event.getAction() == KeyEvent.ACTION_DOWN) {
openSettingsActivity();
return true; // 不再向下分发
}
return super.dispatchKeyEvent(event);
}
private void initListener() {
binding.settingsButton.setOnClickListener(view -> openSettingsActivity());
}
@@ -158,14 +181,28 @@ public class BuildingDashboardActivity extends FullscreenActivity {
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
webSettings.setJavaScriptEnabled(true);
// 禁用缩放相关设置
webSettings.setTextZoom(100);
webSettings.setSupportZoom(false); // 禁止缩放
webSettings.setBuiltInZoomControls(false);
binding.webview.setInitialScale(100);
binding.webview.setWebViewClient(new WebViewClient() {
private boolean hasError = false;
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
hasError = false;
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request,
WebResourceError error) {
super.onReceivedError(view, request, error);
// 只处理主页面的错误,不处理资源文件错误
if (request.getUrl().toString().equals(mainUrl)) {
if (request.isForMainFrame()) {
hasError = true;
handleLoadError();
}
}
@@ -174,9 +211,8 @@ public class BuildingDashboardActivity extends FullscreenActivity {
public void onReceivedHttpError(WebView view, WebResourceRequest request,
WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
// 处理HTTP错误如404, 500等
if (request.getUrl().toString().equals(mainUrl)) {
if (request.isForMainFrame() && errorResponse.getStatusCode() >= 400) {
hasError = true;
handleLoadError();
}
}
@@ -184,15 +220,12 @@ public class BuildingDashboardActivity extends FullscreenActivity {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// 页面加载成功,重置重试计数
if (url.equals(mainUrl)) {
if (!hasError) {
retryCount = 0;
Log.d("WebView", "页面加载成功: " + url);
Log.d("WebView", "加载OK");
}
}
});
}
private void initConfigLoader() {

View File

@@ -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>

View File

@@ -5,166 +5,6 @@
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:fillColor="#065994"
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>
</vector>

View File

@@ -0,0 +1,16 @@
<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">
<group android:scaleX="0.75"
android:scaleY="0.75"
android:translateX="13.5"
android:translateY="13.5">
<path
android:pathData="m36.75,60.38c0,-1.13 -0.38,-2.25 -1.13,-3 -0.75,-0.75 -1.88,-1.5 -3,-1.5 -1.13,0 -2.25,0.75 -3,1.5 -0.75,0.75 -1.5,1.88 -1.5,3 0,1.13 0.38,2.25 1.13,3 0.75,0.75 1.88,1.13 3,1.13 1.13,0 2.25,-0.38 3,-1.13 0.75,-0.75 1.5,-1.88 1.5,-3zM43.13,45.38c0,-1.13 -0.38,-2.25 -1.13,-3 -0.75,-0.75 -1.88,-1.5 -3,-1.5 -1.13,0 -2.25,0.38 -3,1.13 -0.75,0.75 -1.13,2.25 -1.13,3.38 0,1.13 0.38,2.25 1.13,3 0.75,0.75 1.88,1.13 3,1.13 1.13,0 2.25,-0.38 3,-1.13 0.75,-0.75 1.13,-1.88 1.13,-3zM57.75,61.5 L61.13,48.75c0,-0.75 0,-1.13 -0.38,-1.5C60.38,46.5 60,46.13 59.63,46.13L57.75,46.13C57.38,46.5 57,46.88 57,47.63l-3.38,12.75c-1.5,0 -2.63,0.75 -3.75,1.5 -1.13,0.75 -1.88,1.88 -2.25,3.38 -0.38,1.88 -0.38,3.38 0.75,4.88 0.75,1.5 2.25,2.63 3.75,3 1.5,0.38 3.38,0.38 4.88,-0.75 1.5,-0.75 2.63,-2.25 3,-3.75 0.38,-1.5 0.38,-2.63 -0.38,-3.75 0,-1.5 -0.75,-2.63 -1.88,-3.38zM79.88,60.38c0,-1.13 -0.38,-2.25 -1.13,-3 -0.75,-0.75 -1.88,-1.13 -3,-1.13 -1.13,0 -2.25,0.38 -3,1.13 -0.75,0.75 -1.13,1.88 -1.13,3 0,1.13 0.38,2.25 1.13,3 0.75,0.75 1.88,1.13 3,1.13 1.13,0 2.25,-0.38 3,-1.13 0.38,-0.75 1.13,-1.88 1.13,-3zM58.13,39c0,-1.13 -0.38,-2.25 -1.13,-3 -0.75,-1.13 -1.88,-1.5 -3,-1.5 -1.13,0 -2.25,0.38 -3,1.13 -0.75,1.13 -1.13,2.25 -1.13,3.38 0,1.13 0.38,2.25 1.13,3 0.75,0.75 1.88,1.13 3,1.13 1.13,0 2.25,-0.38 3,-1.13 0.75,-0.75 1.13,-1.88 1.13,-3zM73.13,45.38c0,-1.13 -0.38,-2.25 -1.13,-3 -0.75,-0.75 -1.88,-1.13 -3,-1.13 -1.13,0 -2.25,0.38 -3,1.13 -0.75,0.75 -1.13,1.88 -1.13,3 0,1.13 0.38,2.25 1.13,3 0.75,0.75 1.88,1.13 3,1.13 1.13,0 2.25,-0.38 3,-1.13 0.75,-0.75 1.13,-1.88 1.13,-3zM84,60.38c0,6 -1.5,11.25 -4.88,16.13C78.75,77.25 78,77.63 77.25,77.63L30.38,77.63c-0.75,0 -1.5,-0.38 -1.88,-1.13C25.5,71.63 24,66 24,60.38 24,56.25 24.75,52.5 26.25,48.75 27.75,45 30,42 32.63,39c2.63,-3 6,-4.88 9.75,-6.38 3.75,-1.5 7.5,-2.25 11.63,-2.25 4.13,0 7.88,0.75 11.63,2.25 3.75,1.5 6.75,3.75 9.75,6.38 2.63,2.63 4.88,6 6.38,9.75 1.5,3.75 2.25,7.5 2.25,11.63z"
android:strokeWidth="0.0585938"
android:fillColor="#ffffff"/>
</group>
</vector>

View File

@@ -1,6 +1,5 @@
<?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" />
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -1,6 +1,5 @@
<?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" />
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@@ -0,0 +1,7 @@
<resources>
<string-array name="url_end_point_entries">
<item>自动跳转</item>
<item>按楼层</item>
<item>网格+统计</item>
</string-array>
</resources>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">仪表盘</string>
<string name="title_activity_building_dashboard">教学楼仪表盘</string>
<string name="title_activity_settings">设置</string>
</resources>

View File

@@ -9,4 +9,16 @@
<item>reply</item>
<item>reply_all</item>
</string-array>
<string-array name="url_end_point_entries">
<item>Auto Redirect</item>
<item>Floor</item>
<item>Grid+Statics</item>
</string-array>
<string-array name="url_end_point_values">
<item>/</item>
<item>/dashboards/1</item>
<item>/dashboards/2</item>
</string-array>
</resources>

View File

@@ -1,22 +1,6 @@
<resources>
<string name="app_name">Dashboard</string>
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="title_activity_building_dashboard">BuildingDashboardActivity</string>
<string name="title_activity_settings">SettingsActivity</string>
<!-- Preference Titles -->
<string name="messages_header">Messages</string>
<string name="sync_header">Sync</string>
<!-- Messages Preferences -->
<string name="signature_title">Your signature</string>
<string name="reply_title">Default reply action</string>
<!-- Sync Preferences -->
<string name="sync_title">Sync email periodically</string>
<string name="attachment_title">Download incoming attachments</string>
<string name="attachment_summary_on">Automatically download attachments for incoming emails
</string>
<string name="attachment_summary_off">Only download attachments when manually requested</string>
<string name="title_activity_building_dashboard">Building Dashboard</string>
<string name="title_activity_settings">Settings</string>
<string name="url_end_point_default_value" translatable="false">/</string>
</resources>

View File

@@ -1,9 +1,16 @@
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="网页地址">
<EditTextPreference
app:key="k_url"
app:key="k_url_prefix"
app:title="URL 前缀"
app:defaultValue="http://172.18.22.211:8002/Dashboard"
app:useSimpleSummaryProvider="true" />
<ListPreference
app:title="仪表盘风格"
app:key="k_url_end_point"
app:useSimpleSummaryProvider="true"
app:entries="@array/url_end_point_entries"
app:entryValues="@array/url_end_point_values"
app:defaultValue="@string/url_end_point_default_value" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -1,10 +1,70 @@
# Dashboard Client
## 说明
* 这是一个临时项目,功能很简单,全屏轮播几张图片
## 1. 简介
本项目是一个运行在 Android 设备上的仪表盘Dashboard客户端。
其主要功能是作为一个**仪表盘Dashboard**的展示端:它通过全屏 `WebView` 加载并展示一个远程的网页仪表盘,并根据服务器数据的配置,在预定的时间通过串口与外部硬件设备进行通信。
## TODO
## 2. 主要功能
* 可以指定本地和网络图片
* **网页仪表盘展示**:通过 `WebView` 全屏展示一个可配置的远程 URL。
* **远程配置**:应用会定期从服务器获取 `config.json` 文件,动态更新其行为。
* **定时串口指令**:根据 `config.json` 中的计划,使用 `AlarmManager` 在精确的时间点发送十六进制Hex串口指令。
* **开机自启**:设备启动后,应用会自动运行。
* **网络重试机制**:当加载仪表盘主页失败时,应用会自动进行延时重试。
## 3. 工作流程
1. **启动**:应用启动后,进入全屏模式并加载在设置中配置的远程网页 URL。
2. **加载配置**:应用会定期从服务器的 `/data/config.json` 路径下拉取配置文件。
3. **解析与调度**:解析 `config.json` 中定义的串口设备路径、波特率以及多个定时指令。
4. **设置定时任务**:使用 Android 的 `AlarmManager` 为每一条指令安排一个在未来特定时间触发的广播。
5. **执行指令**:当预定时间到达,`CommandBroadcastReceiver` 被唤醒,并通过 `SerialControlDevices` 类向指定的串口发送 Hex 指令。
## 4. 配置
### 4.1 仪表盘 URL
在应用的设置界面中,可以配置仪表盘的主 URL例如 `http://192.168.1.100:8000/Dashboard`。应用会自动加载该 URL 下的 `index.html`
### 4.2 串口指令 (config.json)
应用会从 `[主 URL]/data/config.json` 加载串口指令。`config.json` 的格式如下:
```json
{
"DevicePath": "/dev/ttyS2",
"Baud": 9600,
"Commands": [
{
"Time": "08:00",
"Hex": "AABB0101CCDD"
},
{
"Time": "18:00",
"Hex": "AABB0100CCDD"
}
]
}
```
* `DevicePath`: 串口设备节点路径。
* `Baud`: 串口通信的波特率。
* `Commands`: 一个指令数组,包含多个定时任务。
* `Time`: 指令每天执行的时间24小时制
* `Hex`: 需要发送的十六进制指令字符串。
## 5. 如何构建
这是一个标准的 Android Gradle 项目。使用 Android Studio 打开即可,或在命令行中执行以下命令构建:
```bash
# 构建 Release 版本的 APK
./gradlew clean assembleRelease
```
## 6. TODO
* [ ] 恢复并优化图片轮播功能,支持本地与网络图片。
* [ ] 提供更丰富的远程配置选项(如轮播间隔、动画效果等)。
* [ ] 增加 Web 与客户端通过 Javascript Interface 的双向交互。