ScanService.cs
4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using System;
using Microsoft.Maui.Controls;
#if ANDROID
using Android.Content;
using Android.Util; // ✅ 用于 Log
using IndustrialControl.Droid; // 需要 DynamicScanReceiver
#endif
namespace IndustrialControl.Services
{
public class ScanService
{
public event Action<string, string>? Scanned;
public string? Prefix { get; set; }
public string? Suffix { get; set; }
public int DebounceMs { get; set; } = 250;
private string? _lastData;
private DateTime _lastAt = DateTime.MinValue;
public const string BroadcastAction = "lc";
public const string DataKey = "data";
public const string TypeKey = "SCAN_BARCODE_TYPE_NAME";
public void Attach(Entry entry)
{
entry.Completed += (s, e) =>
{
var data = entry.Text?.Trim();
if (!string.IsNullOrEmpty(data))
{
#if ANDROID
Log.Info("ScanService", $"[Attach] Entry.Completed -> {data}");
#endif
Scanned?.Invoke(data, "kbd");
entry.Text = string.Empty;
}
};
entry.TextChanged += (s, e) =>
{
if (string.IsNullOrEmpty(e.NewTextValue)) return;
if (e.NewTextValue.EndsWith("\n") || e.NewTextValue.EndsWith("\r"))
{
var data = e.NewTextValue.Trim();
#if ANDROID
Log.Info("ScanService", $"[Attach] Entry.TextChanged -> {data}");
#endif
Scanned?.Invoke(data, "kbd");
entry.Text = string.Empty;
}
};
}
public void Publish(string code, string type = "")
{
#if ANDROID
Log.Info("ScanService", $"[Publish] 模拟扫码 -> {code}, type={type}");
#endif
FilterAndRaise(code, type);
}
public void StartListening()
{
#if ANDROID
Android.Util.Log.Info("ScanService", "[StartListening] ENTER");
if (_receiver != null) return;
_receiver = new DynamicScanReceiver();
_receiver.OnScanned += OnScannedFromPlatform;
_filter = new IntentFilter(BroadcastAction);
Android.App.Application.Context.RegisterReceiver(_receiver, _filter);
Log.Info("ScanService", $"[StartListening] 已注册广播 Action={BroadcastAction}");
#endif
}
public void StopListening()
{
#if ANDROID
if (_receiver == null) return;
try
{
Android.App.Application.Context.UnregisterReceiver(_receiver);
Log.Info("ScanService", "[StopListening] 已注销广播");
}
catch (Exception ex)
{
Log.Warn("ScanService", $"[StopListening] 注销异常: {ex.Message}");
}
_receiver.OnScanned -= OnScannedFromPlatform;
_receiver = null;
_filter = null;
#endif
}
private bool FilterAndRaise(string data, string type)
{
if (!string.IsNullOrEmpty(Prefix) && data.StartsWith(Prefix))
data = data.Substring(Prefix.Length);
if (!string.IsNullOrEmpty(Suffix) && data.EndsWith(Suffix))
data = data.Substring(0, data.Length - Suffix.Length);
var now = DateTime.UtcNow;
if (_lastData == data && (now - _lastAt).TotalMilliseconds < DebounceMs)
{
#if ANDROID
Log.Info("ScanService", $"[FilterAndRaise] 数据去抖: {data}");
#endif
return false;
}
_lastData = data;
_lastAt = now;
#if ANDROID
Log.Info("ScanService", $"[FilterAndRaise] 最终触发 -> {data}, type={type}");
#endif
Scanned?.Invoke(data, type);
return true;
}
#if ANDROID
private DynamicScanReceiver? _receiver;
private IntentFilter? _filter;
private void OnScannedFromPlatform(string data, string type)
{
Log.Info("ScanService", $"[OnScannedFromPlatform] 原始数据 -> {data}, type={type}");
FilterAndRaise(data, type);
}
#endif
}
}