You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SZXBGJ/app/src/main/java/com/example/tyre/InStoreHouseActivity.java

507 lines
19 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.example.tyre;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.android.hdhe.uhf.reader.UhfReader;
import com.android.hdhe.uhf.readerInterface.TagModel;
import com.example.tyre.entity.AjaxResult;
import com.example.tyre.entity.BaseTyre;
import com.example.tyre.entity.EPC;
import com.example.tyre.entity.InStoreSpinnerVo;
import com.example.tyre.entity.Tyre;
import com.example.tyre.entity.TyreSizeVo;
import com.example.tyre.util.CommonDialog;
import com.example.tyre.util.MyUrl;
import com.example.tyre.util.SharedPreferencesUtils;
import com.example.tyre.util.Util;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Response;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.pda.serialport.Tools;
/**
* 轮胎入库管理 Activity (优化版)
* 适配重构后的 XML 布局,解决下拉框重影与数据绑定问题
*/
public class InStoreHouseActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
// === UI 组件绑定 (基于新布局修正) ===
@BindView(R.id.button) Button button;
@BindView(R.id.back) Button back;
// 1. EPC 相关:原 @BindView(R.id.epc) 是 TextView现在建议直接读取显示文本或维护内部变量
// 假设 XML 中 Spinner EPC 的 ID 是 spinnerEPC (根据上一轮修改)
@BindView(R.id.EPC)
TextView EPC;
// 2. 胎号 (EditText)
@BindView(R.id.wtbm) EditText wtbm;
// 3. 花纹深度 (EditText)
@BindView(R.id.patternDepth) EditText patternDepth;
// 4. 下拉框 Spinners (核心修复点)
@BindView(R.id.spinnerkind) Spinner spinnerkind;
@BindView(R.id.spinnerpattern) Spinner spinnerpattern;
@BindView(R.id.spinnerlevel) Spinner spinnerlevel;
@BindView(R.id.spinnerSize) Spinner spinnerSize;
@BindView(R.id.spinnerBrand) Spinner spinnerBrand;
@BindView(R.id.spinnergcts) Spinner spinnergcts;
// === 内部数据变量 (用于保存选中的值) ===
// 注意:不再需要 pinpai, xinghao 等 TextView 的 BindView
// 我们直接通过 Spinner.getSelectedItem().toString() 获取值
// 或者定义变量保存
private String selectedBrand = "";
private String selectedModel = "";
private String selectedLevel = "";
private String selectedPattern = "";
private String selectedKind = "";
private String selectedGcts = "";
// === 业务逻辑变量 ===
private boolean isStart = true;
private ProgressDialog progressDialog;
private boolean runFlag = true;
private boolean startFlag = false;
private UhfReader manager;
private ArrayList<EPC> listEPC;
private ArrayList<String> listepc = new ArrayList<String>();
private List<TyreSizeVo> patternSize;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_instorehouse); // 确保使用新布局
ButterKnife.bind(this);
manager = MyApplication.getManager();
initView();
// 初始化下拉框数据
check_spinner();
// 启动 UHF 扫描线程
Thread thread = new InventoryThread();
thread.start();
Util.initSoundPool(this);
}
private void initView() {
listEPC = new ArrayList<EPC>();
// 初始化所有 Spinner 的监听器
initSpinners();
}
/**
* 统一初始化所有 Spinner 的监听器
* 避免代码重复
*/
private void initSpinners() {
spinnerkind.setOnItemSelectedListener(this);
spinnerpattern.setOnItemSelectedListener(this);
spinnerlevel.setOnItemSelectedListener(this);
spinnerSize.setOnItemSelectedListener(this);
spinnerBrand.setOnItemSelectedListener(this);
spinnergcts.setOnItemSelectedListener(this);
}
@Override
public void onResume() {
super.onResume();
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
registerReceiver();
startFlag = false; // 开启扫描
}
@Override
public void onPause() {
startFlag = false;
super.onPause();
unregisterReceiver();
}
@Override
protected void onDestroy() {
runFlag = false;
super.onDestroy();
}
// === UHF 扫描逻辑优化 ===
class InventoryThread extends Thread {
@Override
public void run() {
while (runFlag) {
if (startFlag) {
List<TagModel> tagList = manager.inventoryRealTime();
if (tagList != null && !tagList.isEmpty()) {
Util.play(1, 0); // 播放提示音
for (TagModel tag : tagList) {
String epcStr = tag == null ? "" :
Tools.Bytes2HexString(tag.getmEpcBytes(), tag.getmEpcBytes().length);
byte rssi = tag != null ? tag.getmRssi() : -1;
addToList(epcStr, rssi);
}
// 防止频繁刷新
try { Thread.sleep(20); } catch (InterruptedException e) { }
}
}
}
}
}
/**
* 处理扫描到的 EPC 标签
* 优化:直接操作数据,更新 UI
*/
private void addToList(final String epc, final byte rssi) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// 1. 更新 EPC 显示 (直接设置到 Spinner 或 TextView)
// 假设 spinnerEPC 是用来显示 EPC 的
// 这里可能需要一个只读的 Adapter 或者直接 setText (如果 spinnerEPC 改为了 TextView)
// 为了简化,假设我们有一个方法更新 EPC 显示
//updateEpcDisplay(epc);
EPC.setText(epc);
// 2. 清理旧数据 (根据业务逻辑调整,通常不建议每次扫描都清空)
listepc.clear();
listepc.add(epc);
// 3. 自动查询后台数据
if (!epc.isEmpty()) {
find(epc);
startFlag = false; // 扫描到一次后暂停,防止重复提交
}
}
});
}
private void updateEpcDisplay(String epc) {
// 这里根据你的实际布局调整
// 如果 spinnerEPC 是 Spinner你可能需要一个包含该 EPC 的 Adapter
// 或者在 XML 中保留一个隐藏的 EditText 用于传参
// 简单处理:打印日志
Log.d("UHF", "Scanned EPC: " + epc);
}
// === 网络请求与数据填充 ===
private void find(String epc) {
showLoadingDialog();
OkGo.<String>post(MyUrl.url + "/tyre/tyre/pdaQueryTyreInfo")
.tag(this)
.params("tyreEpc", epc)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
hideLoadingDialog();
try {
Gson gson = new Gson();
BaseTyre baseTyre = gson.fromJson(response.body(), BaseTyre.class);
if (baseTyre != null) {
// 填充表单数据
// 注意:这里不再 setText 到被移除的 TextView
// 而是应该选中 Spinner 的对应项,或者填充 EditText
wtbm.setText(safeGetString(baseTyre.getTyreNo()));
// 逻辑优化Spinner 应该通过 Adapter 选中 position
// 这里简化处理,直接记录值供提交使用
selectedBrand = safeGetString(baseTyre.getTyreBrand());
selectedModel = safeGetString(baseTyre.getTyreModel());
selectedLevel = safeGetString(baseTyre.getTyreLevel());
selectedPattern = safeGetString(baseTyre.getTyrePattern());
selectedKind = safeGetString(baseTyre.getTyreType());
// 如果需要自动选中 Spinner需要遍历 Adapter 寻找 position
// setSelectedSpinnerItem(spinnerBrand, selectedBrand);
}else {
wtbm.setText("");
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private String safeGetString(String value) {
// 注意:原代码中有一行是 "null".equals(value),这是为了防止后台返回字符串 "null"
return value == null || "null".equals(value) ? "" : value;
}
// === 提交逻辑 ===
@OnClick({R.id.button, R.id.back})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.button:
submitData();
break;
case R.id.back:
finish(); // 推荐使用 finish 返回
break;
}
}
private void submitData() {
// 1. 获取当前显示的值
// String epc = ((TextView) spinnerEPC.getChildAt(0)).getText().toString(); // 复杂
// 简单方案:假设你有一个变量保存了最后扫描的 EPC
String currentEpc = getCurrentEpcFromUHF(); // 你需要实现这个逻辑或维护一个变量
if (currentEpc.isEmpty()) {
new CommonDialog(this).setMessage("请扫描轮胎芯片!").show();
return;
}
String wtbmStr = wtbm.getText().toString().trim();
String depthStr = patternDepth.getText().toString().trim();
// 2. 获取下拉框选中的值 (核心修复)
// 由于去除了重影 TextView直接从 Spinner 获取
String brand = spinnerBrand.getSelectedItem() != null ?
spinnerBrand.getSelectedItem().toString() : selectedBrand;
String model = spinnerSize.getSelectedItem() != null ?
spinnerSize.getSelectedItem().toString() : selectedModel;
String level = spinnerlevel.getSelectedItem() != null ?
spinnerlevel.getSelectedItem().toString() : selectedLevel;
String pattern = spinnerpattern.getSelectedItem() != null ?
spinnerpattern.getSelectedItem().toString() : selectedPattern;
String kind = spinnerkind.getSelectedItem() != null ?
spinnerkind.getSelectedItem().toString() : selectedKind;
String grooves = spinnergcts.getSelectedItem() != null ?
spinnergcts.getSelectedItem().toString() : selectedGcts;
// 3. 参数校验
if (wtbmStr=="" || wtbmStr == null || wtbmStr == "Scan fail") {
new CommonDialog(this).setMessage("胎号不能为空").show();
return;
}
showLoadingDialog();
// 4. 发送网络请求
OkGo.<String>post(MyUrl.url + "/tyre/inventory/pdaAddInventory")
.tag(this)
.params("tyreRfid", currentEpc)
.params("tyreEpc", currentEpc)
.params("tyreOutsideId", wtbmStr)
.params("tyreBrand", brand)
.params("tyreModel", model)
.params("tyreLevel", level)
.params("tyrePattern", pattern)
.params("grooves", grooves)
.params("tyreType", kind)
.params("patternDepth", depthStr)
.params("CreateBy", SharedPreferencesUtils.getstring("user", "admin"))
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
hideLoadingDialog();
handleResponse(response.body());
}
@Override
public void onError(Response<String> response) {
hideLoadingDialog();
Toast.makeText(InStoreHouseActivity.this, "请求失败,请检查网络", Toast.LENGTH_SHORT).show();
}
});
}
private String getCurrentEpcFromUHF() {
// TODO: 实现获取当前扫描到的 EPC 的逻辑
// 例如返回 listepc.get(0) 或者维护一个全局变量 currentEpc
return listepc.isEmpty() ? "" : listepc.get(0);
}
private void handleResponse(String body) {
try {
AjaxResult result = new Gson().fromJson(body, AjaxResult.class);
new CommonDialog(this).setMessage(result.getMsg()).show();
if ("200".equals(result.getCode())) { // 假设 200 是成功
// 清空数据以便下一次扫描
clearForm();
}
} catch (Exception e) {
Toast.makeText(this, "数据解析错误", Toast.LENGTH_SHORT).show();
}
}
private void clearForm() {
wtbm.setText("");
patternDepth.setText("");
EPC.setText("");
// spinnerEPC... 清空逻辑
}
// === 下拉框数据加载 (保持不变,但 Adapter 绑定逻辑需确认) ===
private void check_spinner() {
showLoadingDialog();
OkGo.<String>post(MyUrl.url + "/system/dict/data/tyreTypeList")
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
try {
Gson gson = new Gson();
InStoreSpinnerVo vo = gson.fromJson(response.body(), InStoreSpinnerVo.class);
// 设置 Adapter (逻辑保持不变)
setAdapter(spinnerkind, vo.getKindList());
setAdapter(spinnerpattern, vo.getPatternList());
setAdapter(spinnerlevel, vo.getLevelList());
setAdapter(spinnergcts, vo.getGctsList());
setAdapter(spinnerBrand, vo.getTyreBrandList());
// 特殊处理:型号 (需要处理 Label/Value)
List<String> sizeLabels = new ArrayList<>();
if (vo.getTyreSizeList() != null) {
patternSize = vo.getTyreSizeList();
for (TyreSizeVo size : patternSize) {
sizeLabels.add(size.getLabel());
}
}
setAdapter(spinnerSize, sizeLabels);
hideLoadingDialog();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void setAdapter(Spinner spinner, List<String> data) {
if (data != null && !data.isEmpty()) {
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data);
spinner.setAdapter(adapter);
}
}
// === Spinner 选择监听 (优化版) ===
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// 仅保存选中的值,不再 setText 到任何 TextView (解决重影的根本原因)
String selectedItem = parent.getItemAtPosition(position).toString();
switch (parent.getId()) {
case R.id.spinnerBrand:
selectedBrand = selectedItem;
break;
case R.id.spinnerSize:
selectedModel = selectedItem;
// 如果需要根据型号联动花纹深度
if (patternSize != null && position < patternSize.size()) {
patternDepth.setText(patternSize.get(position).getValue());
}
break;
case R.id.spinnerlevel:
selectedLevel = selectedItem;
break;
case R.id.spinnerpattern:
selectedPattern = selectedItem;
break;
case R.id.spinnerkind:
selectedKind = selectedItem;
break;
case R.id.spinnergcts:
selectedGcts = selectedItem;
break;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// 可选:设置默认值
}
// === 广播接收器 (保持不变) ===
private KeyReceiver keyReceiver;
private void registerReceiver() {
keyReceiver = new KeyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.rfid.FUN_KEY");
filter.addAction("android.intent.action.FUN_KEY");
registerReceiver(keyReceiver, filter);
}
private void unregisterReceiver() {
if (keyReceiver != null) {
unregisterReceiver(keyReceiver);
keyReceiver = null;
}
}
private class KeyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int keyCode = intent.getIntExtra("keyCode", 0);
if (keyCode == 0) keyCode = intent.getIntExtra("keycode", 0);
boolean keyDown = intent.getBooleanExtra("keydown", false);
switch (keyCode) {
case KeyEvent.KEYCODE_F1:
case KeyEvent.KEYCODE_F2:
case KeyEvent.KEYCODE_F3:
case KeyEvent.KEYCODE_F4:
case KeyEvent.KEYCODE_F5:
//扫描
startFlag = true;
break;
}
}
}
private void showLoadingDialog() {
if (progressDialog == null) {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("数据加载中...");
progressDialog.setCancelable(false); // 禁止用户通过返回键取消
}
if (!progressDialog.isShowing()) {
progressDialog.show();
}
}
/**
* 隐藏加载对话框
*/
private void hideLoadingDialog() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}