我正在编写一个使用和外部连接USB条形码/ RFID扫描仪的应用程序。正在扫描的数据是"复合"数据。这是一个例子:
=+03000=W12560712345600=%2800&>0090452359
那是来自复合数据扫描。数据中的分隔符是等号(=)或&符号(&)。第一位=+03000
表示扫描中有三个数据部分:
=W12560712345600
=%2800
&>0090452359
此数据可以包含从1到N的任意数量的数据部分。
在我的Android应用中,我有一个包含三个EditText
元素的表单。我需要对这个复合扫描数据做的是使用分隔符将其分解,并将每个数据粘贴到正确的EditText
字段中。
经过多次痛苦之后,我已经意识到我不能只操纵标准输入,并且我需要在我的TextWatcher
个字段之一上使用EditText
来捕获扫描数据所以我可以操纵它。
我的问题是我无法弄清楚如何做到这一点。这就是我所拥有的:
activity_main.xml中
<LinearLayout>
<TextView />
<EditText android:id="@+id/datafield01" />
<EditText android:id="@+id/datafield02" />
<EditText android:id="@+id/datafield03" />
<Button />
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText dataField01 = (EditText)findViewById(R.id.datafield01);
EditText dataField02 = (EditText)findViewById(R.id.datafield02);
EditText dataField02 = (EditText)findViewById(R.id.datafield03);
dataField01.addTextChangedListener(editTextWatcher);
}
TextWatcher editTextWatcher = new TextWatcher(){
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count){
}
@Override
public void afterTextChanged(CharSequence s){
}
};
}
我尝试将CharSequence
捕获到StringBuffer
- 使用before,on和afterTextChanged - 所以我可以操纵它并将其放入正确的EditText
元素中,但我有没有成功。
修改后的MainActivity.java
public class MainActivity extends AppCompatActivity {
private StringBuffer stringBuffer;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
stringBuffer = new StringBuffer();
EditText dataField01 = (EditText)findViewById(R.id.datafield01);
EditText dataField02 = (EditText)findViewById(R.id.datafield02);
EditText dataField02 = (EditText)findViewById(R.id.datafield03);
dataField01.addTextChangedListener(editTextWatcher);
System.out.println(stringBuffer.toString());
}
TextWatcher editTextWatcher = new TextWatcher(){
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count){
stringBuffer.append(s);
}
@Override
public void afterTextChanged(CharSequence s){
}
};
}
每当我尝试System.out.println(stringbuffer);
时,那里什么都没有。
扫描的代码没有给出换行符或任何其他类型的分隔符,它已经结束,数据部分的数量可以是1到N,但每个数据部分确实具有已知的固定长度。
必须有其他人做这样的事情,但我的谷歌搜索没有结果。
那么,有没有办法完成我想要做的事情,或者我完全没有运气?
感谢。
答案 0 :(得分:0)
我确信有一些方法可以通过一些TextWatcher
实现来执行此操作;当你看到分隔符char等时切换焦点
但是当我知道您拥有条形码扫描仪的所有输入时,我认为它更容易处理。然后,您可以简单地解析数据并将其放在适当的位置。
所以诀窍就是弄明白你何时拥有所有扫描仪输入,以便你可以解析它。
这里有一些代码使用了我从查看适用的Android Filter
类中学到的技巧。对于多个快速按键,只有一次过滤延迟机制。 (可悲的是,它是谷歌的私人所以我们凡人都不应该使用这个有用的功能。)
由于您的扫描仪看起来像键盘,因此按键暂停应表示扫描仪已完成输入。让我们用它来确定扫描何时完成。
首先,我们定义一个回调接口只是因为我是一个IoC类型的人:
interface ScanProcessor {
void process(CharSequence input);
}
现在我们定义一个Handler
类。这个处理程序将在主(UI)线程上运行,因此我们不能在处理器中忙碌。
public static class InputDelayHandler extends Handler {
private static final int INPUT_MESSAGE = 0x20170308;
private static final int PROCESS_MESSAGE = 0x20170309;
// You'll have to tweak this value to ensure all input is entered,
// while the app remains responsive to the scan
private static final long DELAY_MS = 250;
private CharSequence mInput;
private ScanProcessor mScanProcessor;
InputDelayHandler(ScanProcessor scanProcessor) {
super(); // associate the handler with the Looper for the current thread
mScanProcessor = scanProcessor;
}
void setInput(CharSequence input) {
// removing this message is the key to how this works
// since it's delayed, we can cancel before input is complete.
removeMessages(PROCESS_MESSAGE);
removeMessages(INPUT_MESSAGE);
Message inputMessage = obtainMessage(INPUT_MESSAGE);
inputMessage.obj = input;
sendMessage(inputMessage);
Message startMessage = obtainMessage(PROCESS_MESSAGE);
sendMessageDelayed(startMessage, DELAY_MS);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case INPUT_MESSAGE:
// remember the last input
mInput = (CharSequence) msg.obj;
break;
case PROCESS_MESSAGE:
// callback
if (/*mInput looks like valid scan data*/) {
mScanProcessor.process(mInput);
}
break;
}
}
}
具有EditText
字段的类应该保留对处理程序的引用。
private InputDelayHandler mHandler;
现在你的TextWatcher
只需要告诉处理程序发生的事情:
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mHandler.setInput(s);
}
这将它们联系在一起:
mHandler = new InputDelayHandler(new ScanProcessor() {
@Override void process(CharSequence input) {
// parse the input, set the EditText fields, etc.
}
});
答案 1 :(得分:0)
首先,您应该将TextWatcher设置为所有3个字段,这样哪个字段具有焦点是不重要的。然后只关注afterTextChanged
<table id = "datatable" class="table table-striped table-bordered" style="font-size: 85%">
<thead>
<tr>
<th class="bg-primary col-sm-2" >
<font size="4">
Employee
</font>
</th>
{{--<th class="bg-danger">--}}
{{--<font size="4">--}}
{{--Company--}}
{{--</font>--}}
{{--</th>--}}
{{--<th class="bg-success">--}}
{{--<font size="4">--}}
{{--Category--}}
{{--</font>--}}
{{--</th>--}}
{{--<th class="bg-warning">--}}
{{--<font size="4">--}}
{{--Task--}}
{{--</font>--}}
{{--</th>--}}
</tr>
</thead>
<tbody>
@foreach ($report_table_all as $report)
<?php
$name = $report[0]['user_name'];
$user_designation = $report[0]['user_designation'];
?>
<tr>
<td>
{{--<font size="2">--}}
<strong>{{$name}}</strong></br>
{{--</font>--}}
<font size="1">
{{$user_designation}}
</font>
</td>
<td>
@foreach ( $report as $daily_report )
<table class="table table-striped table-bordered datatable" style="font-size: 85%">
<thead>
<tr class="primary" style="font-size: 15px;">
<th class="bg-info">Concern</th>
<th class="bg-warning">Category</th>
<th class="bg-success">Task</th>
<th class="bg-danger">Date</th>
</tr>
</thead>
<?php
$total = 0;
$sn = 1;
$sn_total = '*';
?>
@foreach($daily_report['user_task_lists'] as $user_task)
<tr>
<td style="background-color: rgba(227, 255, 140, 0.98); ">
<center>{{$user_task->workfor_name}}</center>
</td>
<td>
<table class="table table-striped table-bordered datatable" style="font-size: 85%">
<tr>
<td style="font-size: 13px;background-color: rgba(19, 214, 255, 0.98)">
{{$sn}}.{{ $user_task->taskcategory_name }}
<?php $sn += floatval(1) ?>
</td>
</tr>
</table>
</td>
<td style="font-size: 12px;">
{{ $user_task->description}}
</td>
<td>
{{date('d-M-Y',strtotime($user_task->task_date))}}
</td>
</tr>
@endforeach
</table>
</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
答案 2 :(得分:0)
这里你真正想做的事情包括几个部分:
实现这一点的正确方法首先是添加正确的权限:
<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />
然后,添加您的意图,“知道”如何处理扫描数据:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
然后,您希望在单独的res xml文件中添加您的应用支持的NFC技术:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
最后,将您的活动绑定到AndroidManifest.xml文件中的intent:
<activity>
...
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
...
</activity>
收到数据后,您希望将消息分成3个部分,如您所示,除以'='符号或'&amp;'签名:
Parcelable [] rawMsgs = intent.getParcelableArrayExtra( NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage msg =(NdefMessage)rawMsgs [0]; String st = new String(msg.getRecords()[0] .getPayload()); ST。 String [] tokens = st.split(“= |&amp;”);
完成后,令牌数组应保留您的消息。
https://developer.android.com/guide/topics/connectivity/nfc/nfc.html#tag-dispatch