本人还是小白,最近在写一个app,需要和嵌入式端一直保持联系;有个功能是把程序传输到嵌入式端,需要每发送一段命令,就要求收到嵌入式端的回复,之后才能继续发送下一段命令,请问大佬们是怎么写的,或者有没有教程可以参考一下。
我现在写的程序没办法在接收到回复以后继续执行发送下一段命令,程序如下:
public class loadActivity extends AppCompatActivity {
private MqttHelper mqttHelper;
private Handler handler;
private Button confirmButton;
private Button cancleButton;
private String account="0000";
private String passwd="0000";
private EditText editTextAccout;
private EditText editTextPasswd;
final String[] items4 = new String[]{"电机", "面板"};//弹窗item
private int index=0;
private static final int READ_REQUEST_CODE = 42;
private Uri filePathUri=null; //下面用于存放回传的文件地址。
private ScheduledExecutorService scheduler;
private int num;//表示未响应时间
private byte[] motorSend={0x10,0x02,0x40,0x00,0x00,0x42,0x10,0x03};
private byte[] panelSend={0x10,0x02,0x41,0x00,0x00,0x43,0x10,0x03};
private byte[] motorComplete={0x10,0x02,0x44,0x00,0x00,0x46,0x10,0x03};
private byte[] panelComplete={0x10,0x02,0x45,0x00,0x00,0x47,0x10,0x03};
private byte[] motorSendReceive={0x10,0x02,0x40,0x00,0x01,0x43,0x10,0x03};
private byte[] PanelSendReceive={0x10,0x02,0x41,0x00,0x01,0x44,0x10,0x03};
private byte[] motorCompleteReceive={0x10,0x02,0x44,0x00,0x01,0x47,0x10,0x03};
private byte[] panelCompleteReceive={0x10,0x02,0x45,0x00,0x01,0x48,0x10,0x03};
private byte[] motorUpdate={0x10,0x02,0x46,0x00,0x01,0x47,0x10,0x03};
private byte[] panelUpdate={0x10,0x02,0x47,0x00,0x01,0x48,0x10,0x03};
private boolean isMotor=false;//表示更新的是电机还是
private int sector = 0; // 用于跟踪当前的sector值
private boolean waitingForResponse = true; // 用于等待回应标志
private byte bytes[];
private ProgressDialog progressDialog;//进度条弹窗
private AlertDialog alertDialog2;//更新对象对话框
private AlertDialog alertDialog5;//返回弹窗
private AlertDialog waitingDialog;//
private boolean isWaitingForResponse;//回应是否超时
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.load);
//取消按钮
cancleButton = findViewById(R.id.button5);
cancleButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
finish();
}
});
editTextAccout = findViewById(R.id.editTextAccout);
editTextPasswd = findViewById(R.id.editTextPasswd);
//确认按钮
confirmButton = findViewById(R.id.button6);
confirmButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
switch(v.getId()){
case R.id.button6:
//getText() 返回的是一个 Editable 对象,而不是一个 String
String inputAccount = editTextAccout.getText().toString();
String inputPasswd = editTextPasswd.getText().toString();
if (inputAccount.equals(account) && inputPasswd.equals(passwd)) {
//申请sd读写权限
int permission_write = ContextCompat.checkSelfPermission(loadActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permission_read = ContextCompat.checkSelfPermission(loadActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE);
if (permission_write != PackageManager.PERMISSION_GRANTED
|| permission_read != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(loadActivity.this, "正在请求权限", Toast.LENGTH_SHORT).show();
//申请权限,特征码自定义为1,可在回调时进行相关判断
ActivityCompat.requestPermissions(loadActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
pickFile();//选择文件
break;
}else{
Toast.makeText(loadActivity.this, "账号密码错误", Toast.LENGTH_SHORT).show();
}
}
}
});
handler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 3:
byte[] receivedMessage;
try {
receivedMessage = ((String)msg.obj).getBytes("UTF-8");
parseByteobj(receivedMessage);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
break;
case 50:
// 更新进度
int progress = (int) msg.obj;
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.setProgress(progress);
}
break;
case 51:
// 传输完成,关闭进度对话框
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
if (waitingForResponse) {
Waiting();
}else{
// 如果不在等待响应,直接显示完成对话框
finishingDialog();
}
}
break;
default:
break;
}
}
};
mqttHelper= ((MyApplication) getApplication()).getMqttHelper();
mqttHelper.connect();
mqttHelper.setHandler(handler);
}
//选择文件之后
private ActivityResultLauncher<Intent> filePickerLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
if (data != null) {
// 处理文件选择
filePathUri = data.getData();
// 显示对话框
showDialog();
}
}
}
);
// 启动文件选择
private void pickFile() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
filePickerLauncher.launch(intent);
}
// 更新对象对话框
private void showDialog() {
alertDialog2 = new AlertDialog.Builder(this)
.setTitle("请选择更新对象")
.setSingleChoiceItems(items4, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
index = i;
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
try {
bytes=readLocalFile(filePathUri);
waitingTransDialog();
} catch (IOException e) {
e.printStackTrace();
}
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
})
.create();
alertDialog2.show();
}
// 进度条弹窗
private void waitingTransDialog() {
progressDialog = new ProgressDialog(this);
progressDialog.setTitle("程序更新中···");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMax(100);
progressDialog.setCancelable(false);
progressDialog.show();
// 开始文件传输
if (index == 0) { //电机
int unsignedValue = motorSend[2] & 0xFF; // 对应的无符号值为 128
mqttHelper.publishMessage(mqttHelper.getPubTopic(), motorSend);
// 等待回应
waitingForResponse = true;
num=0;
if(setWaitingForResponse()) {
unsignedValue = bytes[2] & 0xFF; // 对应的无符号值为 128
// mqttHelper.publishMessageWithProgress(mqttHelper.getPubTopic(), bytes);
sendBytesWithHeaderAndFooter(bytes);
//接收到回复以后发送结束命令
mqttHelper.publishMessage(mqttHelper.getPubTopic(), motorComplete);
}
} else { //面板
int unsignedValue = panelSend[2] & 0xFF; // 对应的无符号值为 128
mqttHelper.publishMessage(mqttHelper.getPubTopic(), panelSend);
// 等待回应
waitingForResponse = true;
num=0;
// if(setWaitingForResponse()) {
// unsignedValue = bytes[2] & 0xFF; // 对应的无符号值为 128
//// mqttHelper.publishMessageWithProgress(mqttHelper.getPubTopic(), bytes);
// sendBytesWithHeaderAndFooter(bytes);
// mqttHelper.publishMessage(mqttHelper.getPubTopic(), panelComplete);
// }
}
}
// 发送 bytes 数组,并添加头部和尾部
private void sendBytesWithHeaderAndFooter(byte[] bytes) {
int segmentSize = 512 - 6; // 每段实际数据长度(减去头尾字节长度)
int totalSegments = (int) Math.ceil((double) bytes.length / segmentSize);
sector = 0; // 重置sector值
sendNextSegment(bytes, segmentSize, totalSegments);
}
// 发送下一段数据
private void sendNextSegment(byte[] bytes, int segmentSize, int totalSegments) {
if (sector < totalSegments) {
int start = sector * segmentSize;
int end = Math.min(start + segmentSize, bytes.length);
byte[] segment = createSegment(bytes, start, end);
mqttHelper.publishMessageWithProgress(mqttHelper.getPubTopic(), segment);
waitingForResponse = true; // 发送数据后等待回应
} else {
// 全部数据发送完成,发送完成信号
if (index == 0) {
mqttHelper.publishMessage(mqttHelper.getPubTopic(), motorComplete);
} else {
mqttHelper.publishMessage(mqttHelper.getPubTopic(), panelComplete);
}
handler.sendEmptyMessage(51); // 通知完成
}
}
// 接收byte数组
private void parseByteobj(byte[] byteobj) {
int ints[] = new int[byteobj.length / 2];
for (int i = 0; i < byteobj.length; ) {
ints[i / 2] = byteobj[i] * 16 + byteobj[i + 1];
i = i + 2;
}
if (ints.equals(motorCompleteReceive))
waitingForResponse = false; // 收到回应
else if (ints.equals(panelCompleteReceive))
waitingForResponse = false; // 收到回应
byte[] expectedResponse = getExpectedResponseForCurrentSector();
if (Arrays.equals(byteobj, expectedResponse)) {
waitingForResponse = false; // 收到回应
num = 0; // 重置计数
sector++; // 增加sector,准备发送下一段数据
handler.post(() -> sendNextSegment(bytes, 512 - 6, (int) Math.ceil((double) bytes.length / (512 - 6))));
} else {
// 未收到预期回应,可以选择重发或记录日志等处理
}
}
// 根据当前的sector值获取预期的回应
private byte[] getExpectedResponseForCurrentSector() {
byte[] response = new byte[8];
response[0] = 0x10;
response[1] = 0x02;
response[2] = (index == 0) ? (byte) 0x42 : (byte) 0x43;
response[3] = (byte) sector;
response[4] = 0x01;
response[5] = (byte) (0x45 + sector);
response[6] = 0x10;
response[7] = 0x03;
return response;
}
// 检查是否收到回应
private boolean setWaitingForResponse(){
Handler checkResponseHandler = new Handler(Looper.getMainLooper());
Runnable checkResponseRunnable = new Runnable() {
@Override
public void run() {
if (waitingForResponse) {//未收到回应
num++;
Waiting();
if (num >= 5) {
Disconnect();
isWaitingForResponse=false;
} else {
isWaitingForResponse=true;
checkResponseHandler.postDelayed(this, 1000); // 1秒后再次检查
}
}else{//收到了回应
isWaitingForResponse=true;
}
}
};
checkResponseHandler.postDelayed(checkResponseRunnable, 1000); // 1秒后开始检查
return isWaitingForResponse;
}
// 创建包含头尾字节的 segment
private byte[] createSegment(byte[] bytes, int start, int end) {
// 创建新数组,包含头部、原始数据段和尾部
byte[] segment = new byte[(end - start) + 6];
// 设置头部 {0x10, 0x02, 0x42}
segment[0] = 0x10;
segment[1] = 0x02;
if(index==0) segment[2] = 0x42;//电机
else segment[2] = 0x43;//面板
// 拷贝原始数据
System.arraycopy(bytes, start, segment, 3, end - start);
// 设置尾部 {sector, 0x10, 0x03}
segment[segment.length - 3] = (byte) sector; // 设置 sector 值
segment[segment.length - 2] = 0x10;
segment[segment.length - 1] = 0x03;
return segment;
}
private void Waiting() {
waitingDialog = new AlertDialog.Builder(this)
.setMessage("请等待···")
.create();
waitingDialog.show();
}
// 断开对话框
private void Disconnect() {
// 关闭等待中的弹窗
if (waitingDialog != null && waitingDialog.isShowing()) {
waitingDialog.dismiss();
}
AlertDialog alertDialog2 = new AlertDialog.Builder(this)
.setTitle("与主机连接断开,请重新尝试")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(loadActivity.this, MainActivity.class);
startActivity(intent);
}
})
.create();
alertDialog2.show();
}
// 显示返回对话框
private void finishingDialog() {
alertDialog5 = new AlertDialog.Builder(this)
.setTitle("程序更新完毕,是否返回")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(loadActivity.this, MainActivity.class);
startActivity(intent);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
})
.create();
alertDialog5.show();
}
private byte[] readLocalFile(Uri fileName) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(fileName);;
byte[] data = toByteArray(inputStream);
inputStream.close();
return data;
}
private byte[] toByteArray(InputStream inputStream) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}