├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── sjl │ │ └── scanner │ │ └── test │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── sjl │ │ │ └── scanner │ │ │ └── test │ │ │ ├── MainActivity.java │ │ │ ├── MyApplication.java │ │ │ ├── ScannerUsbActivity.java │ │ │ ├── ScannerUsbKeyboardActivity.java │ │ │ ├── SettingActivity.java │ │ │ └── fragment │ │ │ └── MyDialogFragment.java │ └── res │ │ ├── drawable │ │ └── list_item_bg_white.xml │ │ ├── layout │ │ ├── main_activity.xml │ │ ├── my_dialog_fragment.xml │ │ ├── scanner_usb_activity.xml │ │ ├── scanner_usb_keyboard_activity.xml │ │ └── setting_activity.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ └── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── sjl │ └── scanner │ └── test │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── scanner ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── sjl │ │ └── scanner │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── sjl │ │ │ └── scanner │ │ │ ├── BaseUsbScan.java │ │ │ ├── IUsbScan.java │ │ │ ├── MainThreadExecutor.java │ │ │ ├── UsbCmdScan.java │ │ │ ├── UsbComAutoScan.java │ │ │ ├── UsbConfig.java │ │ │ ├── UsbErrorCode.java │ │ │ ├── UsbKeyboardAutoScan.java │ │ │ ├── UsbScanHelper.java │ │ │ ├── listener │ │ │ ├── OnScanListener.java │ │ │ ├── UsbPermissionListener.java │ │ │ └── UsbPlugListener.java │ │ │ └── util │ │ │ ├── ByteUtils.java │ │ │ └── LogUtils.java │ └── res │ │ └── values │ │ ├── attrs.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── sjl │ └── scanner │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | /build 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scanner-master 2 | 3 | Android 扫码枪封装,Android端获取扫码枪数据一般有如下三种获取方式: 4 | 5 | - USB键盘模式,自感模式(出厂默认):大多数扫码枪是模拟键盘进行输入(不支持包含有汉字的二维码),大多数时候需要使用带焦点的 EditText 接收其扫描的信息。设置一个带焦点的EditText进行接收,此方式容易漏读扩展的ASCII码数据,除非二维码是标准的ASCII码(1-128),此外使用EditText不方便且焦点控制不好导致扫码不到数据。由于扫码枪会将扫描出来的内容转化为键盘事件,对应的就是Android中的KeyEvent事件,所以我们只需要在我们的activity中重写dispatchKeyEvent方法,即可获取相应事件。 6 | 7 | - 通过 USB COM连接扫码:发送扫码开关指令进行扫码,即基于Usb相关类控制扫码开关,控制不好容易出问题 8 | **特别地**:使用此模式前提是先对扫码枪配置USB COM模式,再配置指令触发 9 | 10 | - USB串口自感模式:即串口连接(当扫码枪使用 USB 通讯接口,但主机应用程序是采用串口通讯方式接收数据),客户端只负责监听读取数据,无须控制扫码枪指令,需要依赖usb串口传输数据的第三方库:https://github.com/mik3y/usb-serial-for-android 11 | **特别地**:使用此模式前提是先对扫码枪配置USB 虚拟串口通讯方式 12 | 13 | 14 | # 使用 15 | 16 | 步骤 1. 在工程跟目录build.gradle文件下添加仓库 17 | 18 | 19 | allprojects { 20 | repositories { 21 | ... 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | 26 | 步骤2. 添加依赖 27 | 28 | dependencies { 29 | implementation 'com.github.kellysong:scanner-master:1.1.0' 30 | 31 | } 32 | 33 | # 注意 34 | 35 | 1. 使用之前请检查扫码器模式是否设置正确 36 | 2. app build.gradle 配置 37 | 38 | compileOptions { 39 | sourceCompatibility JavaVersion.VERSION_1_8 40 | targetCompatibility JavaVersion.VERSION_1_8 41 | } -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | buildToolsVersion '29.0.3' 6 | 7 | defaultConfig { 8 | applicationId "com.sjl.test" 9 | minSdkVersion 17 10 | targetSdkVersion 28 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | compileOptions { 21 | sourceCompatibility JavaVersion.VERSION_1_8 22 | targetCompatibility JavaVersion.VERSION_1_8 23 | } 24 | } 25 | 26 | 27 | dependencies { 28 | implementation fileTree(include: ['*.jar'], dir: 'libs') 29 | testImplementation 'junit:junit:4.12' 30 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 31 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 32 | implementation 'androidx.appcompat:appcompat:1.0.0' 33 | implementation project(':scanner') 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in F:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/sjl/scanner/test/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.sjl.scanner.test; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static junit.framework.TestCase.assertEquals; 11 | 12 | @RunWith(AndroidJUnit4.class) 13 | public class ApplicationTest { 14 | @Test 15 | public void useAppContext() { 16 | // Context of the app under test. 17 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 18 | 19 | assertEquals("com.sjl.scanner.test", appContext.getPackageName()); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 29 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/sjl/scanner/test/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.sjl.scanner.test; 2 | 3 | import android.content.Intent; 4 | import android.hardware.usb.UsbDevice; 5 | import android.os.Bundle; 6 | import androidx.annotation.Nullable; 7 | import androidx.appcompat.app.AppCompatActivity; 8 | import android.view.View; 9 | 10 | import com.sjl.scanner.UsbScanHelper; 11 | import com.sjl.scanner.listener.UsbPlugListener; 12 | 13 | /** 14 | * TODO 15 | * 16 | * @author Kelly 17 | * @version 1.0.0 18 | * @filename MainActivity 19 | * @time 2020/9/26 13:30 20 | * @copyright(C) 2020 song 21 | */ 22 | public class MainActivity extends AppCompatActivity { 23 | @Override 24 | protected void onCreate(@Nullable Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.main_activity); 27 | 28 | } 29 | 30 | 31 | public void testUsbKeyboard(View view) { 32 | startActivity(new Intent(this,ScannerUsbKeyboardActivity.class)); 33 | } 34 | 35 | 36 | public void testUsbConnect(View view) { 37 | startActivity(new Intent(this,ScannerUsbActivity.class)); 38 | } 39 | 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/sjl/scanner/test/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.sjl.scanner.test; 2 | 3 | import android.app.Application; 4 | 5 | import com.sjl.scanner.UsbScanHelper; 6 | import com.sjl.scanner.util.LogUtils; 7 | 8 | /** 9 | * TODO 10 | * 11 | * @author Kelly 12 | * @version 1.0.0 13 | * @filename MyApplication 14 | * @time 2022/6/2 15:53 15 | * @copyright(C) 2022 song 16 | */ 17 | public class MyApplication extends Application { 18 | 19 | @Override 20 | public void onCreate() { 21 | super.onCreate(); 22 | LogUtils.init(true); 23 | UsbScanHelper.getInstance().init(this); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/sjl/scanner/test/ScannerUsbActivity.java: -------------------------------------------------------------------------------- 1 | package com.sjl.scanner.test; 2 | 3 | import android.content.Intent; 4 | import android.hardware.usb.UsbDevice; 5 | import android.os.Bundle; 6 | import android.text.TextUtils; 7 | import android.view.View; 8 | import android.widget.AdapterView; 9 | import android.widget.ArrayAdapter; 10 | import android.widget.Button; 11 | import android.widget.EditText; 12 | import android.widget.LinearLayout; 13 | import android.widget.Spinner; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.sjl.scanner.BaseUsbScan; 18 | import com.sjl.scanner.UsbCmdScan; 19 | import com.sjl.scanner.UsbComAutoScan; 20 | import com.sjl.scanner.UsbConfig; 21 | import com.sjl.scanner.UsbScanHelper; 22 | import com.sjl.scanner.listener.OnScanListener; 23 | import com.sjl.scanner.listener.UsbPermissionListener; 24 | import com.sjl.scanner.listener.UsbPlugListener; 25 | import com.sjl.scanner.util.LogUtils; 26 | 27 | import java.text.SimpleDateFormat; 28 | import java.util.ArrayList; 29 | import java.util.Arrays; 30 | import java.util.Date; 31 | import java.util.List; 32 | 33 | import androidx.appcompat.app.AppCompatActivity; 34 | 35 | /** 36 | * 基于usb扫码 37 | * 38 | * @author song 39 | */ 40 | public class ScannerUsbActivity extends AppCompatActivity { 41 | BaseUsbScan usbScan; 42 | EditText et_barcode; 43 | TextView tv_msg; 44 | Button btn_connect_setting; 45 | LinearLayout ll_operation; 46 | public static UsbConfig usbConfig = new UsbConfig(); 47 | private Spinner spinner_connect_way, spinner_device; 48 | private int connectWay; 49 | private String deviceName; 50 | private static final String DEVICE_SEPARATOR = " "; 51 | 52 | @Override 53 | protected void onCreate(Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | setContentView(R.layout.scanner_usb_activity); 56 | et_barcode = findViewById(R.id.et_barcode); 57 | tv_msg = findViewById(R.id.tv_msg); 58 | spinner_connect_way = findViewById(R.id.spinner_connect_way); 59 | spinner_device = findViewById(R.id.spinner_device); 60 | btn_connect_setting = findViewById(R.id.btn_connect_setting); 61 | ll_operation= findViewById(R.id.ll_operation); 62 | btn_connect_setting.setOnClickListener(new View.OnClickListener() { 63 | @Override 64 | public void onClick(View v) { 65 | startActivity(new Intent(ScannerUsbActivity.this, SettingActivity.class)); 66 | } 67 | }); 68 | initSpinner(); 69 | UsbScanHelper.getInstance().registerUsbReceiver(); 70 | UsbScanHelper.getInstance().setUsbPlugListener(new UsbPlugListener() { 71 | @Override 72 | public void onAttached(UsbDevice usbDevice) { 73 | initDeviceList(); 74 | } 75 | 76 | @Override 77 | public void onDetached(UsbDevice usbDevice) { 78 | initDeviceList(); 79 | } 80 | }); 81 | } 82 | 83 | private void initSpinner() { 84 | final List connectWayStr = Arrays.asList("UsbCmdScan", "UsbComAutoScan"); 85 | spinner_connect_way.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, connectWayStr)); 86 | spinner_connect_way.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 87 | @Override 88 | public void onItemSelected(AdapterView parent, View view, final int position, long id) { 89 | LogUtils.i("connectWayStr:" + connectWayStr.get(position)); 90 | connectWay = position; 91 | if (usbScan != null) { 92 | usbScan.closeScan(); 93 | } 94 | if (connectWay == 0) { 95 | usbScan = new UsbCmdScan(ScannerUsbActivity.this); //通过usb连接扫码, 发送命令扫码 96 | } else { 97 | usbScan = new UsbComAutoScan(ScannerUsbActivity.this);//通过usb转串口,自感模式,推荐 98 | } 99 | } 100 | 101 | @Override 102 | public void onNothingSelected(AdapterView parent) { 103 | } 104 | }); 105 | initDeviceList(); 106 | 107 | 108 | } 109 | 110 | private void initDeviceList() { 111 | final List deviceList = new ArrayList<>(); 112 | 113 | List tempDevice = UsbScanHelper.getInstance().getDeviceList(); 114 | for (UsbDevice device : tempDevice) { 115 | deviceList.add(device.getDeviceName() + DEVICE_SEPARATOR + "vid:" + device.getVendorId() + ",pid:" + device.getProductId()); 116 | } 117 | 118 | if (deviceList.size() == 0) { 119 | ll_operation.setVisibility(View.GONE); 120 | showMsg("没有可用设备"); 121 | return; 122 | }else { 123 | ll_operation.setVisibility(View.VISIBLE); 124 | } 125 | 126 | spinner_device.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, deviceList)); 127 | spinner_device.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 128 | @Override 129 | public void onItemSelected(AdapterView parent, View view, final int position, long id) { 130 | LogUtils.i("deviceName:" + deviceList.get(position)); 131 | deviceName = deviceList.get(position); 132 | 133 | } 134 | 135 | @Override 136 | public void onNothingSelected(AdapterView parent) { 137 | } 138 | }); 139 | } 140 | 141 | 142 | public void openUsbScan(View view) { 143 | UsbScanHelper usbScanHelper = UsbScanHelper.getInstance(); 144 | List deviceList = usbScanHelper.getDeviceList(); 145 | if (deviceList.size() == 0) { 146 | Toast.makeText(ScannerUsbActivity.this, "没有可用设备", Toast.LENGTH_LONG).show(); 147 | return; 148 | } 149 | for (final UsbDevice device : deviceList) { 150 | String[] s = deviceName.split(DEVICE_SEPARATOR); 151 | if (device.getDeviceName().equals(s[0])) { 152 | // Request permission 153 | if (usbScanHelper.hasPermission(device)) { 154 | performOpenUsbScan(device); 155 | } else { 156 | usbScanHelper.requestPermission(device, new UsbPermissionListener() { 157 | @Override 158 | public void onGranted() { 159 | performOpenUsbScan(device); 160 | } 161 | 162 | @Override 163 | public void onDenied() { 164 | showMsg("无usb权限"); 165 | } 166 | }); 167 | } 168 | break; 169 | } 170 | } 171 | 172 | 173 | } 174 | 175 | private void performOpenUsbScan(UsbDevice device) { 176 | if (usbScan == null) { 177 | return; 178 | } 179 | usbConfig.setProductId(device.getProductId()); 180 | usbConfig.setVendorId(device.getVendorId()); 181 | usbScan.setOnScanListener(new OnScanListener() { 182 | @Override 183 | public void onScanSuccess(String barcode) { 184 | et_barcode.setText(barcode); 185 | } 186 | }); 187 | int ret = usbScan.openScan(usbConfig); 188 | if (ret != 0) { 189 | showMsg("打开usb扫码失败,ret" + ret); 190 | } else { 191 | showMsg("打开usb扫码成功"); 192 | } 193 | } 194 | 195 | 196 | public void closeUsbScan(View view) { 197 | usbScan.closeScan(); 198 | showMsg("关闭usb扫码成功"); 199 | } 200 | 201 | public void loopScan(View view) { 202 | usbScan.startReading(); 203 | } 204 | 205 | public void stopLoopScan(View view) { 206 | usbScan.stopReading(); 207 | } 208 | 209 | @Override 210 | protected void onDestroy() { 211 | super.onDestroy(); 212 | usbScan.closeScan(); 213 | UsbScanHelper.getInstance().unregisterUsbReceiver(); 214 | } 215 | 216 | 217 | private void showMsg(String s) { 218 | 219 | final String str = s; 220 | runOnUiThread(new Runnable() { 221 | @Override 222 | public void run() { 223 | Date curDate = new Date(System.currentTimeMillis()); 224 | String strDate = new SimpleDateFormat("HH:mm:ss.SSS").format(curDate); 225 | //已有的log 226 | String log = tv_msg.getText().toString().trim(); 227 | if (TextUtils.isEmpty(log)) { 228 | log = strDate + ": " + str; 229 | } else { 230 | log += "\r\n" + strDate + ": " + str; 231 | } 232 | tv_msg.setText(log); 233 | //自动滚动 234 | tv_msg.post(() -> { 235 | int scrollAmount = tv_msg.getLayout().getLineTop(tv_msg.getLineCount()) - tv_msg.getHeight(); 236 | tv_msg.scrollTo(0, scrollAmount > 0 ? scrollAmount : 0); 237 | }); 238 | } 239 | }); 240 | 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /app/src/main/java/com/sjl/scanner/test/ScannerUsbKeyboardActivity.java: -------------------------------------------------------------------------------- 1 | package com.sjl.scanner.test; 2 | 3 | import android.os.Bundle; 4 | import androidx.fragment.app.FragmentManager; 5 | import androidx.appcompat.app.AppCompatActivity; 6 | import android.view.KeyEvent; 7 | import android.view.View; 8 | import android.widget.EditText; 9 | 10 | import com.sjl.scanner.UsbKeyboardAutoScan; 11 | import com.sjl.scanner.listener.OnScanListener; 12 | import com.sjl.scanner.test.fragment.MyDialogFragment; 13 | 14 | /** 15 | * usb键盘模式扫码示例,无需EditText接收,推荐 16 | * 17 | * @author song 18 | */ 19 | public class ScannerUsbKeyboardActivity extends AppCompatActivity { 20 | UsbKeyboardAutoScan usbKeyboardAutoScan; 21 | EditText et_barcode; 22 | MyDialogFragment dialogFragment; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.scanner_usb_keyboard_activity); 28 | et_barcode = findViewById(R.id.et_barcode); 29 | usbKeyboardAutoScan = new UsbKeyboardAutoScan(); 30 | initScanListener(); 31 | 32 | } 33 | 34 | private void initScanListener() { 35 | usbKeyboardAutoScan.setOnScanListener(new OnScanListener() { 36 | @Override 37 | public void onScanSuccess(String barcode) { 38 | et_barcode.setText(barcode); 39 | } 40 | }); 41 | } 42 | 43 | @Override 44 | protected void onStart() { 45 | super.onStart(); 46 | } 47 | 48 | @Override 49 | public boolean dispatchKeyEvent(KeyEvent event) { 50 | if (usbKeyboardAutoScan.isIntercept() 51 | && event.getKeyCode() != KeyEvent.KEYCODE_BACK) {//不处理返回键 52 | usbKeyboardAutoScan.analysisKeyEvent(event); 53 | return true;//防止输入框接收事件 54 | } 55 | return super.dispatchKeyEvent(event); 56 | } 57 | 58 | @Override 59 | protected void onDestroy() { 60 | super.onDestroy(); 61 | usbKeyboardAutoScan.cancel(); 62 | } 63 | 64 | public void btnDialogFragment(View view) { 65 | dialogFragment = new MyDialogFragment(); 66 | FragmentManager supportFragmentManager = getSupportFragmentManager(); 67 | dialogFragment.show(supportFragmentManager, dialogFragment.getClass().getSimpleName()); 68 | dialogFragment.setMyDialogFragmentListener(new MyDialogFragment.MyDialogFragmentListener() { 69 | @Override 70 | public void onDismiss() { 71 | initScanListener(); 72 | } 73 | }); 74 | } 75 | 76 | public UsbKeyboardAutoScan getUsbKeyboardAutoScan() { 77 | return usbKeyboardAutoScan; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/sjl/scanner/test/SettingActivity.java: -------------------------------------------------------------------------------- 1 | package com.sjl.scanner.test; 2 | 3 | import android.os.Bundle; 4 | import android.text.Editable; 5 | import android.text.TextUtils; 6 | import android.text.TextWatcher; 7 | import android.view.View; 8 | import android.widget.EditText; 9 | import android.widget.RelativeLayout; 10 | import android.widget.TextView; 11 | 12 | import com.sjl.scanner.UsbConfig; 13 | import com.sjl.scanner.util.ByteUtils; 14 | 15 | import androidx.annotation.Nullable; 16 | import androidx.appcompat.app.AlertDialog; 17 | import androidx.appcompat.app.AppCompatActivity; 18 | import androidx.appcompat.widget.Toolbar; 19 | 20 | /** 21 | * 扫码设置,保存到内存中 22 | * 23 | * @author Kelly 24 | * @version 1.0.0 25 | * @filename SettingActivity 26 | * @time 2022/6/9 18:00 27 | * @copyright(C) 2022 song 28 | */ 29 | public class SettingActivity extends AppCompatActivity implements View.OnClickListener, TextWatcher { 30 | TextView tvBaudRate; 31 | TextView tvDataBits; 32 | TextView tvStopBits; 33 | TextView tvParity; 34 | EditText et_open_cmd; 35 | EditText et_close_cmd; 36 | 37 | @Override 38 | protected void onCreate(@Nullable Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.setting_activity); 41 | RelativeLayout itemBaudRate = findViewById(R.id.itemBaudRate); 42 | RelativeLayout itemDataBits = findViewById(R.id.itemDataBits); 43 | RelativeLayout itemStopBits = findViewById(R.id.itemStopBits); 44 | RelativeLayout itemParity = findViewById(R.id.itemParity); 45 | tvBaudRate = findViewById(R.id.tvBaudRate); 46 | tvDataBits = findViewById(R.id.tvDataBits); 47 | tvStopBits = findViewById(R.id.tvStopBits); 48 | tvParity = findViewById(R.id.tvParity); 49 | itemBaudRate.setOnClickListener(this); 50 | itemDataBits.setOnClickListener(this); 51 | itemStopBits.setOnClickListener(this); 52 | itemParity.setOnClickListener(this); 53 | 54 | 55 | et_open_cmd = findViewById(R.id.et_open_cmd); 56 | et_close_cmd = findViewById(R.id.et_close_cmd); 57 | et_open_cmd.addTextChangedListener(this); 58 | et_close_cmd.addTextChangedListener(this); 59 | Toolbar toolbar = findViewById(R.id.toolbar); 60 | toolbar.setNavigationOnClickListener(new View.OnClickListener() { 61 | @Override 62 | public void onClick(View v) { 63 | finish(); 64 | } 65 | }); 66 | initDefaultValue(); 67 | } 68 | 69 | private void initDefaultValue() { 70 | final UsbConfig usbConfig = ScannerUsbActivity.usbConfig; 71 | final UsbConfig.SerialPortConfig serialPortConfig = usbConfig.getSerialPortConfig(); 72 | final UsbConfig.ScanCmd scanCmd = usbConfig.getScanCmd(); 73 | tvBaudRate.setText(String.valueOf(serialPortConfig.getBaudRate())); 74 | tvDataBits.setText(String.valueOf(serialPortConfig.getDataBits())); 75 | if (serialPortConfig.getStopBits() == 3) { 76 | tvStopBits.setText("1.5"); 77 | } else { 78 | tvStopBits.setText(String.valueOf(serialPortConfig.getStopBits())); 79 | } 80 | int parity = serialPortConfig.getParity(); 81 | final String[] values = getResources().getStringArray(R.array.parity); 82 | tvParity.setText(values[parity]); 83 | String openCmd = ByteUtils.byteArrToHexString(scanCmd.getScanOpen()); 84 | et_open_cmd.setText(openCmd); 85 | et_open_cmd.setSelection(openCmd.length()); 86 | String closeCmd = ByteUtils.byteArrToHexString(scanCmd.getScanClose()); 87 | et_close_cmd.setText(closeCmd); 88 | et_close_cmd.setSelection(closeCmd.length()); 89 | 90 | } 91 | 92 | private int baudRate = 115200; 93 | private int dataBits = 8; 94 | private int stopBits = 1; 95 | private int parity = 0; 96 | 97 | @Override 98 | public void onClick(View v) { 99 | final UsbConfig usbConfig = ScannerUsbActivity.usbConfig; 100 | final UsbConfig.SerialPortConfig serialPortConfig = usbConfig.getSerialPortConfig(); 101 | 102 | switch (v.getId()) { 103 | case R.id.itemBaudRate: { 104 | final String[] values = getResources().getStringArray(R.array.baudRates); 105 | int pos = java.util.Arrays.asList(values).indexOf(String.valueOf(baudRate)); 106 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 107 | builder.setTitle("波特率"); 108 | builder.setSingleChoiceItems(values, pos, (dialog, which) -> { 109 | dialog.dismiss(); 110 | baudRate = Integer.parseInt(values[which]); 111 | tvBaudRate.setText(values[which]); 112 | serialPortConfig.setBaudRate(baudRate); 113 | }); 114 | builder.create().show(); 115 | break; 116 | } 117 | case R.id.itemDataBits: { 118 | final String[] values = getResources().getStringArray(R.array.dataBits); 119 | int pos = java.util.Arrays.asList(values).indexOf(String.valueOf(dataBits)); 120 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 121 | builder.setTitle("数据位"); 122 | builder.setSingleChoiceItems(values, pos, (dialog, which) -> { 123 | dialog.dismiss(); 124 | dataBits = Integer.parseInt(values[which]); 125 | tvDataBits.setText(values[which]); 126 | serialPortConfig.setDataBits(dataBits); 127 | }); 128 | builder.create().show(); 129 | break; 130 | } 131 | case R.id.itemStopBits: { 132 | final String[] values = getResources().getStringArray(R.array.stopBits); 133 | int pos = 0; 134 | if (stopBits == 1) { 135 | pos = 0; 136 | } else if (stopBits == 3) { 137 | pos = 1; 138 | } else if (stopBits == 2) { 139 | pos = 2; 140 | } 141 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 142 | builder.setTitle("停止位"); 143 | builder.setSingleChoiceItems(values, pos, (dialog, which) -> { 144 | dialog.dismiss(); 145 | if (values[which].equals("1.5")) { 146 | stopBits = 3; 147 | } else { 148 | stopBits = Integer.parseInt(values[which]); 149 | } 150 | tvStopBits.setText(values[which]); 151 | 152 | serialPortConfig.setStopBits(stopBits); 153 | }); 154 | builder.create().show(); 155 | break; 156 | } 157 | case R.id.itemParity: { 158 | final String[] values = getResources().getStringArray(R.array.parity); 159 | 160 | int pos = parity; 161 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 162 | builder.setTitle("校验位"); 163 | builder.setSingleChoiceItems(values, pos, (dialog, which) -> { 164 | dialog.dismiss(); 165 | parity = which; 166 | tvParity.setText(values[which]); 167 | serialPortConfig.setParity(which); 168 | }); 169 | builder.create().show(); 170 | break; 171 | } 172 | default: 173 | break; 174 | } 175 | } 176 | 177 | @Override 178 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 179 | 180 | } 181 | 182 | @Override 183 | public void onTextChanged(CharSequence s, int start, int before, int count) { 184 | final UsbConfig usbConfig = ScannerUsbActivity.usbConfig; 185 | String openCmd = et_open_cmd.getText().toString().trim().replace(" ", ""); 186 | String closeCmd = et_close_cmd.getText().toString().trim().replace(" ", ""); 187 | if (!TextUtils.isEmpty(openCmd) && openCmd.length() % 2 == 0) { 188 | UsbConfig.ScanCmd scanCmd = usbConfig.getScanCmd(); 189 | scanCmd.setScanOpen(ByteUtils.hexStringToByteArr(openCmd)); 190 | } 191 | if (!TextUtils.isEmpty(closeCmd) && closeCmd.length() % 2 == 0) { 192 | UsbConfig.ScanCmd scanCmd = usbConfig.getScanCmd(); 193 | scanCmd.setScanClose(ByteUtils.hexStringToByteArr(closeCmd)); 194 | } 195 | 196 | } 197 | 198 | @Override 199 | public void afterTextChanged(Editable s) { 200 | 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /app/src/main/java/com/sjl/scanner/test/fragment/MyDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.sjl.scanner.test.fragment; 2 | 3 | import android.app.Dialog; 4 | import android.content.DialogInterface; 5 | import android.os.Bundle; 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | import androidx.fragment.app.DialogFragment; 9 | import android.util.DisplayMetrics; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.view.Window; 14 | import android.widget.EditText; 15 | 16 | import com.sjl.scanner.UsbKeyboardAutoScan; 17 | import com.sjl.scanner.listener.OnScanListener; 18 | import com.sjl.scanner.test.R; 19 | import com.sjl.scanner.test.ScannerUsbKeyboardActivity; 20 | 21 | /** 22 | * TODO 23 | * 24 | * @author Kelly 25 | * @version 1.0.0 26 | * @filename MyDialogFragment 27 | * @time 2021/8/14 10:21 28 | * @copyright(C) 2021 song 29 | */ 30 | public class MyDialogFragment extends DialogFragment { 31 | EditText et_fragment_barcode; 32 | 33 | @Override 34 | public void onStart() { 35 | super.onStart(); 36 | DisplayMetrics displayMetrics = getActivity().getResources().getDisplayMetrics(); 37 | //DialogFragment宽度 38 | getDialog().getWindow().setLayout((int) (displayMetrics.widthPixels * 0.9), (int) (displayMetrics.heightPixels * 0.3)); 39 | } 40 | 41 | @Nullable 42 | @Override 43 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 44 | View inflate = inflater.inflate(R.layout.my_dialog_fragment, container, false); 45 | et_fragment_barcode = inflate.findViewById(R.id.et_fragment_barcode); 46 | return inflate; 47 | 48 | } 49 | 50 | @Override 51 | public void onDismiss(DialogInterface dialog) { 52 | super.onDismiss(dialog); 53 | if (myDialogFragmentListener != null) { 54 | myDialogFragmentListener.onDismiss(); 55 | } 56 | } 57 | 58 | @Override 59 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 60 | super.onActivityCreated(savedInstanceState); 61 | ScannerUsbKeyboardActivity activity = (ScannerUsbKeyboardActivity) getActivity(); 62 | //或者你把UsbKeyboardAutoScan封装成单例,这样就不用通过activity取 63 | UsbKeyboardAutoScan usbKeyboardAutoScan = activity.getUsbKeyboardAutoScan(); 64 | usbKeyboardAutoScan.setOnScanListener(new OnScanListener() {//覆盖了ScannerUsbKeyboardActivity的监听,收不到信息,一般都是一处地方接收扫码结果 65 | @Override 66 | public void onScanSuccess(String barcode) { 67 | et_fragment_barcode.setText(barcode); 68 | } 69 | }); 70 | } 71 | 72 | @NonNull 73 | @Override 74 | public Dialog onCreateDialog(Bundle savedInstanceState) { 75 | Dialog dialog = super.onCreateDialog(savedInstanceState); 76 | //设置actionbar的隐藏 77 | dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 78 | return dialog; 79 | } 80 | 81 | private MyDialogFragmentListener myDialogFragmentListener; 82 | 83 | public interface MyDialogFragmentListener { 84 | void onDismiss(); 85 | } 86 | 87 | public void setMyDialogFragmentListener(MyDialogFragmentListener myDialogFragmentListener) { 88 | this.myDialogFragmentListener = myDialogFragmentListener; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list_item_bg_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/main_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 |