commit 073acc35c265982fa2720c53d849ed4b6b5a38aa Author: wanghao Date: Tue Nov 18 11:15:30 2025 +0800 version 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..2e0bad6 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +xie biao qian \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..2813088 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..4750179 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d5d35ec --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..797acea --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..0d78ab1 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,44 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 29 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.example.xiebiaoqian" + minSdkVersion 22 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.constraintlayout:constraintlayout:2.0.1' + implementation files('libs\\pdasdk_v2.25_20190328.jar') + implementation files('libs\\jxl-2.6.12.jar') + testImplementation 'junit:junit:4.+' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation 'org.litepal.android:java:3.0.0' + implementation 'com.jakewharton:butterknife:10.2.0' + annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.0' +} \ No newline at end of file diff --git a/app/libs/jxl-2.6.12.jar b/app/libs/jxl-2.6.12.jar new file mode 100644 index 0000000..4a1fc64 Binary files /dev/null and b/app/libs/jxl-2.6.12.jar differ diff --git a/app/libs/pdasdk_v2.25_20190328.jar b/app/libs/pdasdk_v2.25_20190328.jar new file mode 100644 index 0000000..60c6337 Binary files /dev/null and b/app/libs/pdasdk_v2.25_20190328.jar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json new file mode 100644 index 0000000..e64a71f --- /dev/null +++ b/app/release/output-metadata.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.example.xiebiaoqian", + "variantName": "release", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "versionCode": 1, + "versionName": "1.0", + "outputFile": "app-release.apk" + } + ] +} \ No newline at end of file diff --git a/app/release/昊华越南-科陆7202kPDA写标签程序v2025111801.apk b/app/release/昊华越南-科陆7202kPDA写标签程序v2025111801.apk new file mode 100644 index 0000000..a66cf4a Binary files /dev/null and b/app/release/昊华越南-科陆7202kPDA写标签程序v2025111801.apk differ diff --git a/app/src/androidTest/java/com/example/xiebiaoqian/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/xiebiaoqian/ExampleInstrumentedTest.java new file mode 100644 index 0000000..01c0941 --- /dev/null +++ b/app/src/androidTest/java/com/example/xiebiaoqian/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.example.xiebiaoqian; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.example.xiebiaoqian", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6669b8d --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/litepal.xml b/app/src/main/assets/litepal.xml new file mode 100644 index 0000000..dc8a4b4 --- /dev/null +++ b/app/src/main/assets/litepal.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/xiebiaoqian/MainActivity.java b/app/src/main/java/com/example/xiebiaoqian/MainActivity.java new file mode 100644 index 0000000..b87a18c --- /dev/null +++ b/app/src/main/java/com/example/xiebiaoqian/MainActivity.java @@ -0,0 +1,311 @@ +package com.example.xiebiaoqian; + +import android.annotation.SuppressLint; +import android.content.res.AssetFileDescriptor; +import android.media.MediaPlayer; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.PopupMenu; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.example.xiebiaoqian.entity.WriteInfo; +import com.example.xiebiaoqian.utils.ASCIIUtil; +import com.example.xiebiaoqian.utils.JxlExporter; +import com.pda.rfid.EPCModel; +import com.pda.rfid.IAsynchronousMessage; +import com.pda.rfid.uhf.UHFReader; + +import org.litepal.LitePal; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + +public class MainActivity extends AppCompatActivity implements IAsynchronousMessage, PopupMenu.OnMenuItemClickListener { + + @BindView(R.id.spinner1) + Spinner spinner1; + @BindView(R.id.spinner2) + Spinner spinner2; + @BindView(R.id.editTextNumber) + EditText editTextNumber; + @BindView(R.id.write_info) + EditText writeInfo; + @BindView(R.id.san_epc_code) + TextView sanEpcCode; + @BindView(R.id.san_redly_tag) + TextView sanRedlyTag; + @BindView(R.id.main_menu) + ImageView mainMenu; + private boolean readType; + private String targetTid = null; + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + playSound(); + if (readType) {//扫描到要写入的标签 + EPCModel epcModel = (EPCModel) msg.obj; + targetTid = epcModel._TID; + sanRedlyTag.setText(targetTid); + Log.e("TAG", "TID读取成功" + targetTid); + } else { + EPCModel epcModel = (EPCModel) msg.obj; + String newCode = ASCIIUtil.hex2Str(epcModel._EPC); + Log.e("TAG", "EPC读取成功" + epcModel._EPC); + sanEpcCode.setText(newCode); + } + + + } + }; + private String epc; + private String epcASCII; + private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化时间 + private SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH_mm_ss");// 格式化时间 + private PopupMenu popupMenu; + private long exitTime;//退出记时 + private JxlExporter exporter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + ButterKnife.bind(this); + popupMenu = new PopupMenu(this, mainMenu); + getMenuInflater().inflate(R.menu.menu, popupMenu.getMenu()); + popupMenu.setOnMenuItemClickListener(this); + List list0 = Arrays.asList(getResources().getStringArray(R.array.list0)); + List list1 = Arrays.asList(getResources().getStringArray(R.array.list1)); + List list2 = Arrays.asList(getResources().getStringArray(R.array.list2)); + spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + if (i == 0) { + + spinner2.setAdapter(new ArrayAdapter<>(MainActivity.this, R.layout.support_simple_spinner_dropdown_item, list0)); + } else if (i == 1) { + spinner2.setAdapter(new ArrayAdapter<>(MainActivity.this, R.layout.support_simple_spinner_dropdown_item, list1)); + } else if (i == 2) { + spinner2.setAdapter(new ArrayAdapter<>(MainActivity.this, R.layout.support_simple_spinner_dropdown_item, list2)); + } + + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + + } + + + }); + exporter = new JxlExporter(this); + } + + @SuppressLint({"NonConstantResourceId", "DefaultLocale"}) + @OnClick({R.id.main_menu, R.id.button_low, R.id.button_add, R.id.rule_create, R.id.button_epc_write, R.id.button_san_epc, R.id.button_clera_view, R.id.button_info_seva, R.id.button_san_tag}) + public void onClick(View view) { + switch (view.getId()) { + case R.id.main_menu: + popupMenu.show(); + break; + case R.id.button_san_tag: + Log.e("tag", "onClick: 读取待写标签"); + readType = true; + UHFReader._Tag6C.GetEPC_TID(1, 1); + break; + case R.id.button_low: + inputNumber(true); + break; + case R.id.button_add: + inputNumber(false); + break; + case R.id.rule_create: + String writeData = spinner2.getSelectedItem().toString(); + String code = writeData.split("-")[1]; + String codeEnd = editTextNumber.getText().toString().trim(); + if (spinner2.getSelectedItem().toString().equals("胶桌托盘-JLTP")) { + codeEnd = String.format("%04d", Integer.parseInt(codeEnd)); + } else { + codeEnd = String.format("%03d", Integer.parseInt(codeEnd)); + } + writeInfo.setText(code + codeEnd); + + break; + case R.id.button_epc_write://写入 + if (targetTid == null) { + Toast.makeText(this, "先读取待写入标签", Toast.LENGTH_SHORT).show(); + return; + } + String writeDataRedly = writeInfo.getText().toString(); + epc = writeDataRedly; + if (writeDataRedly.isEmpty()) { + Toast.makeText(this, "先按规则生成写入编码", Toast.LENGTH_SHORT).show(); + return; + } + String asciiData = ASCIIUtil.str2Hex(writeDataRedly); + Log.e("TAG", "转换后: " + asciiData); + int length = asciiData.length(); + if (length < 16) { + asciiData += String.format("%0" + (16 - length) + "d", 0); + } + epcASCII = asciiData.toUpperCase(); + Log.e("TAG", "写入的数据为:" + asciiData + ",长度为" + asciiData.length()); + int writeResult = UHFReader._Tag6C.WriteEPC_MatchTID(1, asciiData, targetTid, 0); + Toast.makeText(this, writeResult == 0 ? "写入成功,点击下方扫描进行验证" : "写入失败", Toast.LENGTH_SHORT).show(); + break; + case R.id.button_san_epc: + if (targetTid == null) { + Toast.makeText(this, "先读取待写入标签", Toast.LENGTH_SHORT).show(); + return; + } + readType = false; + UHFReader._Tag6C.GetEPC_MatchTID(1, 1, targetTid); + break; + case R.id.button_clera_view: + targetTid = null; + epc = null; + epcASCII = null; + sanEpcCode.setText(null); + sanRedlyTag.setText(null); + writeInfo.setText(null); + break; + case R.id.button_info_seva: + if (targetTid.isEmpty() || epc.isEmpty() || epcASCII.isEmpty()) return; + WriteInfo writeInfo = new WriteInfo(); + writeInfo.setTid(targetTid); + writeInfo.setEpc(epc); + writeInfo.setEpcASCII(epcASCII); + writeInfo.setDateTime(sdf.format(new Date())); + writeInfo.save(); + Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show(); + break; + } + } + + @SuppressLint("SetTextI18n") + private void inputNumber(boolean state) { + String tag = editTextNumber.getText().toString(); + if (tag.isEmpty()) { + editTextNumber.setText("1"); + return; + } + int data = Integer.parseInt(tag); + if (state) { + if (data == 1) { + return; + } + data--; + } else { + if (data == 9999) { + return; + } + data++; + } + editTextNumber.setText(data + ""); + } + + //初始化驱动 + @Override + protected void onResume() { + super.onResume(); + + UHFReader._Config.OpenConnect(false, this); + UHFReader._Config.SetANTPowerParam(2, 24); + } + + //关闭驱动 + @Override + protected void onDestroy() { + super.onDestroy(); + UHFReader._Config.Stop(); + UHFReader._Config.CloseConnect(); + handler = null; + } + + //读取到标签 + @Override + public void OutPutEPC(EPCModel epcModel) { + UHFReader._Config.Stop(); + Message msg = new Message(); + msg.obj = epcModel; + handler.sendMessage(msg); + } + + //播放声音 + private void playSound() { + // 每次播放创建新的MediaPlayer + MediaPlayer mediaPlayer = new MediaPlayer(); + try { + // 设置数据源(示例:raw目录下的sound.mp3) + AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.msg); + mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); + afd.close(); + + // 准备(同步准备适合短音效,异步准备需监听OnPreparedListener) + mediaPlayer.prepare(); + + // 设置播放完成监听,释放资源 + mediaPlayer.setOnCompletionListener(mp -> { + mp.release(); // 播放完成后释放 + }); + + // 设置错误监听,避免异常崩溃 + mediaPlayer.setOnErrorListener((mp, what, extra) -> { + mp.release(); + return true; + }); + + // 开始播放 + mediaPlayer.start(); + } catch (Exception e) { + e.printStackTrace(); + mediaPlayer.release(); // 发生异常时释放 + } + } + + @Override + public boolean onMenuItemClick(MenuItem menuItem) { +// 导出文件名为"RFID数据_yyyyMMdd_HHmmss.xls"(可自定义) + String fileName = "RFID数据_" + sdf1.format(new Date()) + "1.xls"; + exporter.export(LitePal.findAll(WriteInfo.class), fileName); + + return true; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == 4) { + + if ((System.currentTimeMillis() - exitTime) > 2000) { + //弹出提示,可以有多种方式 + Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show(); + exitTime = System.currentTimeMillis(); + return true; + } else { + finish(); + } + } + return super.onKeyDown(keyCode, event); + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/xiebiaoqian/base/Myapp.java b/app/src/main/java/com/example/xiebiaoqian/base/Myapp.java new file mode 100644 index 0000000..a5cbb01 --- /dev/null +++ b/app/src/main/java/com/example/xiebiaoqian/base/Myapp.java @@ -0,0 +1,14 @@ +package com.example.xiebiaoqian.base; + +import android.app.Application; + +import org.litepal.LitePal; + +public class Myapp extends Application { + + @Override + public void onCreate() { + super.onCreate(); + LitePal.initialize(this); + } +} diff --git a/app/src/main/java/com/example/xiebiaoqian/entity/WriteInfo.java b/app/src/main/java/com/example/xiebiaoqian/entity/WriteInfo.java new file mode 100644 index 0000000..94f075f --- /dev/null +++ b/app/src/main/java/com/example/xiebiaoqian/entity/WriteInfo.java @@ -0,0 +1,51 @@ +package com.example.xiebiaoqian.entity; + +import org.litepal.crud.LitePalSupport; + +public class WriteInfo extends LitePalSupport { + private int id; + private String tid; + private String epc; + private String epcASCII; + private String dateTime; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTid() { + return tid; + } + + public void setTid(String tid) { + this.tid = tid; + } + + public String getEpc() { + return epc; + } + + public void setEpc(String epc) { + this.epc = epc; + } + + public String getDateTime() { + return dateTime; + } + + public void setDateTime(String dateTime) { + this.dateTime = dateTime; + } + + public String getEpcASCII() { + return epcASCII; + } + + public void setEpcASCII(String epcASCII) { + this.epcASCII = epcASCII; + } +} diff --git a/app/src/main/java/com/example/xiebiaoqian/utils/ASCIIUtil.java b/app/src/main/java/com/example/xiebiaoqian/utils/ASCIIUtil.java new file mode 100644 index 0000000..93c4cb9 --- /dev/null +++ b/app/src/main/java/com/example/xiebiaoqian/utils/ASCIIUtil.java @@ -0,0 +1,58 @@ +package com.example.xiebiaoqian.utils; + +/** + * @author: wangh + * @description: Ass + * @date: 2019/06/20-15:18 + */ +public class ASCIIUtil { + + // String明文转ASCII码hex字符串,一个明文字符生成两个字符表示的16进制ASCII码 + public static String str2Hex(String str) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + sb.append(Integer.toString(c, 16)); + } + return sb.toString(); + } + + // ASCII码hex字符串转String明文 + public static String hex2Str(String hex) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hex.length() - 1; i += 2) { + String h = hex.substring(i, (i + 2)); + int decimal = Integer.parseInt(h, 16); + sb.append((char) decimal); + } + return sb.toString(); + + } + public static String hexTo4ZN(String hex) throws Exception { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hex.length() - 1; i += 4) { + String h = hex.substring(i, (i + 4)); + sb.append((char) Integer.parseInt(h, 16)); + } + return sb.toString(); + } + + + public static String str4Hex(String str) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + String s = Integer.toString(str.charAt(i), 16); + sb.append(s.length()==2?"00"+s:s); + } + return sb.toString(); + } + public static String convertToAscii(String chineseText) { + StringBuilder asciiText = new StringBuilder(); + for (int i = 0; i < chineseText.length(); i++) { + char c = chineseText.charAt(i); + int asciiValue = (int) c; + asciiText.append(asciiValue).append(" "); + } + return asciiText.toString().trim(); + } +} diff --git a/app/src/main/java/com/example/xiebiaoqian/utils/JxlExporter.java b/app/src/main/java/com/example/xiebiaoqian/utils/JxlExporter.java new file mode 100644 index 0000000..7112b67 --- /dev/null +++ b/app/src/main/java/com/example/xiebiaoqian/utils/JxlExporter.java @@ -0,0 +1,114 @@ +package com.example.xiebiaoqian.utils; +import android.content.Context; +import android.os.Environment; +import android.widget.Toast; + +import com.example.xiebiaoqian.entity.WriteInfo; + +import jxl.Workbook; +import jxl.write.Label; +import jxl.write.WritableSheet; +import jxl.write.WritableWorkbook; +import jxl.write.WriteException; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * 使用 jxl-2.6.12 导出 Excel(适配 Android 5.1) + */ +public class JxlExporter { + private Context mContext; + + public JxlExporter(Context context) { + this.mContext = context; + } + + /** + * 导出 RFID 数据到 .xls 文件 + */ + public void export(List dataList, String fileName) { + // 确保文件名以 .xls 结尾 + if (!fileName.endsWith(".xls")) { + fileName += ".xls"; + } + + WritableWorkbook workbook = null; + try { + // 1. 获取存储路径(Android 5.1 下载目录) + File file = getFilePath(fileName); + FileOutputStream fos = new FileOutputStream(file); + + // 2. 创建可写入的工作簿 + workbook = Workbook.createWorkbook(fos); + + // 3. 创建工作表(表名:RFID数据记录) + WritableSheet sheet = workbook.createSheet("RFID数据记录", 0); // 索引0表示第一个表 + // 第0列(序号):宽度10 + sheet.setColumnView(0, 10); + // 第1列(TID):宽度20 + sheet.setColumnView(1, 30); + // 第2列(EPC):宽度25 + sheet.setColumnView(2, 15); + // 第3列(EPC_ASCII):宽度15 + sheet.setColumnView(3, 20); + // 第4列(采集时间):宽度20 + sheet.setColumnView(4, 20); + // 4. 写入表头(第一行) + String[] headers = {"序号", "TID", "EPC", "ASCII", "保存时间"}; + for (int i = 0; i < headers.length; i++) { + // Label(列索引, 行索引, 内容) + Label headerLabel = new Label(i, 0, headers[i]); + sheet.addCell(headerLabel); + } + + // 5. 写入数据(从第二行开始,行索引1) + for (int i = 0; i < dataList.size(); i++) { + WriteInfo data = dataList.get(i); + int rowIndex = i + 1; + + // 序号(id) + sheet.addCell(new Label(0, rowIndex, String.valueOf(data.getId()))); + // TID + sheet.addCell(new Label(1, rowIndex, data.getTid() == null ? "" : data.getTid())); + // EPC + sheet.addCell(new Label(2, rowIndex, data.getEpc() == null ? "" : data.getEpc())); + // EPC_ASCII + sheet.addCell(new Label(3, rowIndex, data.getEpcASCII() == null ? "" : data.getEpcASCII())); + // 采集时间 + sheet.addCell(new Label(4, rowIndex, data.getDateTime() == null ? "" : data.getDateTime())); + } + + // 6. 写入文件并关闭工作簿 + workbook.write(); + Toast.makeText(mContext, "导出成功:" + file.getAbsolutePath(), Toast.LENGTH_LONG).show(); + + } catch (IOException | WriteException e) { + e.printStackTrace(); + Toast.makeText(mContext, "导出失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); + } finally { + // 7. 释放资源 + if (workbook != null) { + try { + workbook.close(); + } catch (IOException | WriteException e) { + e.printStackTrace(); + } + } + } + } + + /** + * 获取 Android 5.1 兼容的文件路径 + */ + private File getFilePath(String fileName) { + File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); + if (!downloadDir.exists()) { + downloadDir.mkdirs(); + } + + return new File(downloadDir, fileName); + } +} \ No newline at end of file diff --git a/app/src/main/jniLibs/arm64-v8a/libIAL.so b/app/src/main/jniLibs/arm64-v8a/libIAL.so new file mode 100644 index 0000000..03c5557 Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libIAL.so differ diff --git a/app/src/main/jniLibs/arm64-v8a/libSDL.so b/app/src/main/jniLibs/arm64-v8a/libSDL.so new file mode 100644 index 0000000..a999d93 Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libSDL.so differ diff --git a/app/src/main/jniLibs/arm64-v8a/libbarcodereader44.so b/app/src/main/jniLibs/arm64-v8a/libbarcodereader44.so new file mode 100644 index 0000000..11f4c1d Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libbarcodereader44.so differ diff --git a/app/src/main/jniLibs/arm64-v8a/libcepri_dev.so b/app/src/main/jniLibs/arm64-v8a/libcepri_dev.so new file mode 100644 index 0000000..cf1e8ac Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libcepri_dev.so differ diff --git a/app/src/main/jniLibs/arm64-v8a/libpda.so b/app/src/main/jniLibs/arm64-v8a/libpda.so new file mode 100644 index 0000000..cf8a4ea Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libpda.so differ diff --git a/app/src/main/jniLibs/armeabi/libIAL.so b/app/src/main/jniLibs/armeabi/libIAL.so new file mode 100644 index 0000000..144c43d Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libIAL.so differ diff --git a/app/src/main/jniLibs/armeabi/libSDL.so b/app/src/main/jniLibs/armeabi/libSDL.so new file mode 100644 index 0000000..ba5f77e Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libSDL.so differ diff --git a/app/src/main/jniLibs/armeabi/libbarcodereader.so b/app/src/main/jniLibs/armeabi/libbarcodereader.so new file mode 100644 index 0000000..a50815a Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libbarcodereader.so differ diff --git a/app/src/main/jniLibs/armeabi/libbarcodereader43.so b/app/src/main/jniLibs/armeabi/libbarcodereader43.so new file mode 100644 index 0000000..e055356 Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libbarcodereader43.so differ diff --git a/app/src/main/jniLibs/armeabi/libbarcodereader44.so b/app/src/main/jniLibs/armeabi/libbarcodereader44.so new file mode 100644 index 0000000..071fc53 Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libbarcodereader44.so differ diff --git a/app/src/main/jniLibs/armeabi/libcepri_dev.so b/app/src/main/jniLibs/armeabi/libcepri_dev.so new file mode 100644 index 0000000..915e984 Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libcepri_dev.so differ diff --git a/app/src/main/jniLibs/armeabi/libpda.so b/app/src/main/jniLibs/armeabi/libpda.so new file mode 100644 index 0000000..c45bb64 Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libpda.so differ diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_blue.xml b/app/src/main/res/drawable/button_blue.xml new file mode 100644 index 0000000..3980936 --- /dev/null +++ b/app/src/main/res/drawable/button_blue.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_yellow.xml b/app/src/main/res/drawable/button_yellow.xml new file mode 100644 index 0000000..e608a89 --- /dev/null +++ b/app/src/main/res/drawable/button_yellow.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/text_white.xml b/app/src/main/res/drawable/text_white.xml new file mode 100644 index 0000000..9d3f332 --- /dev/null +++ b/app/src/main/res/drawable/text_white.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..2e884ea --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + +