Android手持机扫码出入库的开发详解-3.出库扫码

45 阅读40分钟

Android手持机扫码出入库的开发详解-3.出库扫码

出库扫码界面

出库扫码程序图

flowchart TD
      A[进入出库扫码界面] --> B[初始化扫码设备]
    B --> C[注册扫码广播接收器]
    C --> D[初始化UI面板和数据库]
    D --> E[等待扫描条码]
    E --> F[扫码设备扫描条码]
    F --> G[mScanReceiver接收扫描结果]
    G --> H[GBK解码获取条码字符串]
    H --> I[parseScanCodeData解析条码类型]
    I -->|长度小于21货位码| J[validationHwh验证货位号]
    I -->|长度大于等于21材料码| K[validationCode验证材料码]
    J -->|验证失败| L[显示错误信息]
    K -->|验证失败| L
    J -->|验证成功| M[显示货位信息]
    K -->|验证成功| N[显示材料信息]
    M --> O{是否已扫描两种码}
    N --> O
    O -->|否| E
    O -->|是| P[CorrelationData关联数据检查]
    P -->|关联失败| Q[显示关联错误]
    Q --> R[重置验证面板]
    R --> E
    P -->|关联成功| S[启用更新按钮]
    S --> T[点击更新按钮]
    T --> U[updateOutData更新数据库]
    U --> V[更新待出库表扫码数量]
    V --> W[插入出库扫码记录]
    W --> X[Refresh_ListView刷新主界面]
    X --> Y{是否所有数量已扫描}
    Y -->|是| R
    Y -->|否| Z[保持验证面板状态]
    Z --> E

出库扫码程序流程说明:

  1. 初始化阶段:进入界面后,程序会初始化扫码设备、注册广播接收器、加载UI面板并初始化数据库连接
  2. 扫码阶段:扫码设备扫描条码后,通过广播接收器接收数据并进行GBK解码
  3. 条码解析:根据条码长度判断是货位码(<21位)还是材料码(≥21位)
  4. 验证阶段:分别对货位码和材料码进行验证,验证失败则显示错误信息
  5. 数据关联:当两种码都扫描完成后,进行货位号和生产日期的一致性检查
  6. 数据更新:验证通过后,更新待出库表中的扫码数量,并将扫描记录插入出库扫码表
  7. UI刷新:更新操作完成后,刷新主界面列表,并根据扫描数量决定是否重置验证面板
  8. 循环处理:完成一次扫码流程后,继续等待下一次扫描

出库扫码源代码

1. 初始化阶段
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_out_storage_scan_code);
    // 获取用户信息
    Intent intent = getIntent();
    Bundle bundle = intent.getExtras();
    this.userName = bundle.getString("userName");
    
    // 初始化扫码设备
    sm = new ScanDevice();
    sm.openScan();
    
    // 注册扫码广播接收器
    IntentFilter filter = new IntentFilter(SCAN_ACTION);
    registerReceiver(mScanReceiver, filter);
    
    // 初始化数据库连接
    OpenOrCreateDatabase();
    
    // 初始化DAO对象
    adao = new AwaitOutStorageDAO();
    dao = new OutStorageDAO();
    bomdao = new BillOfMaterialDAO();
    mdao = new ManufacturerDAO();
    skdao = new StoreKeeperDAO();
    
    // 加载主UI面板
    LinearLayout mainLinearLayout = findViewById(R.id.OutStorageScanCodeMainLinearLayout);
    mainLinearLayout.setVisibility(LinearLayout.VISIBLE);
    // 隐藏其他面板
    HideDownloadDataChildLinearLayout();
    HideSelectDataChildLinearLayout();
    HideValidationChildLinearLayout();
}

// 创建或打开数据库
private void OpenOrCreateDatabase() {
    sda = new SqliteDBConnection(this);
    sda.open();
    db = sda.getDb();
}
2. 扫码阶段
// 扫码广播接收器
private BroadcastReceiver mScanReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 获取扫码数据
        byte[] barocode = intent.getByteArrayExtra("barocode");
        int barocodelen = intent.getIntExtra("length", 0);
        String barcodeStr = null;
        try {
            // GBK解码获取条码字符串
            barcodeStr = new String(barocode, 0, barocodelen, "GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        
        // 调用条码解析方法
        parseScanCodeData(barcodeStr);
        
        // 停止扫码
        sm.stopScan();
    }
};
3. 条码解析
// 条码解析
private void parseScanCodeData(String barcodeStr){
    if (barcodeStr.length() >= 21) {
        // 材料码(≥21位)
        strCode = barcodeStr.toString();
        // 验证材料码
        validationCode(strCode);
    } else {
        // 货位码(<21位)
        strHwh = barcodeStr.toString();
        // 验证货位码
        validationHwh(strHwh);
    }
    // 显示验证面板
    ShowValidationChildLinearLayout();
}
4. 验证阶段
// 货位码验证
private void validationHwh(String strHwh) {
    try {
        // 验证货位码是否存在
        int validationRes = adao.validationOutDataHwh(db, strHwh);
        if (validationRes == 1) {
            // 验证成功
            textView_Validation_货位码验证结果.setText("✔");
            textView_Validation_货位码验证结果.setTextColor(Color.parseColor("#228B22"));
            
            // 查询并显示货位信息
            AwaitOutStorage awaitOutStorage = adao.validationOutDataHwhAndGetInfo(db, strHwh);
            textView_Validation_货位号A.setText(awaitOutStorage.getStr_货位号());
            textView_Validation_生产日期A.setText(awaitOutStorage.getStr_来料日期());
            textView_Validation_库存数量A.setText(String.valueOf(awaitOutStorage.getInt_库存数量()));
            textView_Validation_应发数量A.setText(String.valueOf(awaitOutStorage.getInt_应发数量()));
            textView_Validation_已扫数量A.setText(String.valueOf(awaitOutStorage.getInt_扫码数量()));
            textView_Validation_未扫数量A.setText(String.valueOf(awaitOutStorage.getInt_未扫数量()));
            
            // 检查是否已扫描两种码
            if (strCode != null) {
                CorrelationData(strHwh, strCode);
            }
        } else {
            // 验证失败
            textView_Validation_货位码验证结果.setText("✘");
            textView_Validation_货位码验证结果.setTextColor(Color.RED);
            textView_Validation_Msg.setText("错误:货位码不正确或不存在!");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

// 材料码验证
private void validationCode(String strCode) {
    try {
        // 从材料码中解析信息
        String str_材料条码 = strCode.substring(0, 5);
        String str_厂家代码 = strCode.substring(5, 7);
        String str_生产日期 = ConvertDate(strCode.substring(7, 13));
        String str_批号 = strCode.substring(13, 14);
        String str_扫码数量 = strCode.substring(14, 20);
        
        // 验证材料信息
        int validationRes = adao.validationOutDataCode(db, str_材料条码, str_厂家代码, str_生产日期);
        if (validationRes == 1) {
            // 验证成功
            textView_Validation_材料码验证结果.setText("✔");
            textView_Validation_材料码验证结果.setTextColor(Color.parseColor("#228B22"));
            
            // 查询并显示材料信息
            AwaitOutStorage awaitOutStorage = adao.validationOutDataCodeAndGetInfo(db, str_材料条码, str_厂家代码, str_生产日期);
            textView_Validation_货位号B.setText(awaitOutStorage.getStr_货位号());
            textView_Validation_生产日期B.setText(awaitOutStorage.getStr_来料日期());
            textView_Validation_库存数量B.setText(String.valueOf(awaitOutStorage.getInt_库存数量()));
            textView_Validation_应发数量B.setText(String.valueOf(awaitOutStorage.getInt_应发数量()));
            textView_Validation_已扫数量B.setText(String.valueOf(awaitOutStorage.getInt_扫码数量()));
            textView_Validation_未扫数量B.setText(String.valueOf(awaitOutStorage.getInt_未扫数量()));
            
            // 检查是否已扫描两种码
            if (strHwh != null) {
                CorrelationData(strHwh, strCode);
            }
        } else {
            // 验证失败
            textView_Validation_材料码验证结果.setText("✘");
            textView_Validation_材料码验证结果.setTextColor(Color.RED);
            textView_Validation_Msg.setText("错误:材料码不正确或不匹配!");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
5. 数据关联
// 数据关联检查
private void CorrelationData(String strHwh, String strCode) {
    try {
        // 获取两种码的货位号和生产日期
        String str_货位号A = textView_Validation_货位号A.getText().toString();
        String str_生产日期A = textView_Validation_生产日期A.getText().toString();
        String str_货位号B = textView_Validation_货位号B.getText().toString();
        String str_生产日期B = textView_Validation_生产日期B.getText().toString();
        
        // 检查一致性
        if (str_货位号A.equals(str_货位号B) && str_生产日期A.equals(str_生产日期B)) {
            // 关联成功,启用更新按钮
            button_Validation_UpdateData.setEnabled(true);
            button_Validation_UpdateData.setClickable(true);
        } else {
            // 关联失败
            textView_Validation_Msg.setText("错误:货位号和生产日期不一致!");
            textView_Validation_Msg.setTextColor(Color.RED);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
6. 数据更新
// 数据更新
private void updateOutData() {
    try {
        // 获取相关数据
        String str_货位号 = textView_Validation_货位号A.getText().toString();
        String str_生产日期 = textView_Validation_生产日期A.getText().toString();
        String str_材料条码 = strCode.substring(0, 5);
        String str_厂家代码 = strCode.substring(5, 7);
        String str_扫码数量 = strCode.substring(14, 20);
        
        // 更新待出库表扫码数量
        adao.updateScanCodeSumAdd(db, str_货位号, str_生产日期, str_材料条码, str_厂家代码, str_扫码数量);
        
        // 插入出库扫码记录
        OutStorage outStorage = OutStorage.newInstance();
        outStorage.setStr_货位号(str_货位号);
        outStorage.setStr_扫码时间(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        outStorage.setStr_扫码人(userName);
        outStorage.setStr_扫码仓库("B库");
        // 设置其他出库信息
        // ...
        
        // 向出库扫码表中插入数据
        Cursor dao_cursor = dao.insertData(db, outStorage);
        
        // 重新查询数据
        Cursor cursor = adao.findOutData(db, str_材料条码, str_厂家代码);
        
    } catch (Exception e) {
        e.printStackTrace();
    }
}
7. UI刷新
// 刷新主界面列表
private void Refresh_ListView(Cursor cursor) {
    // 填充SimpleCursorAdapter
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(
            this,
            R.layout.activity_out_storage_scan_code_scan_data_listview,
            cursor,
            new String[]{"_id", "货位号", "材料名称", "材料规格", "颜色", "库管员", "厂家缩写", "CBW对照号", "单位", "材料条码", "厂家代码", "生产日期", "批号", "数量", "库管编码", "码文", "扫码人", "扫码时间", "扫码仓库", "出库编号"},
            new int[]{
                    R.id.textView_listView_OutStorageScanCode_DataList_ID,
                    R.id.textView_listView_OutStorageScanCode_DataList_货位号,
                    // 其他UI控件ID
                    // ...
            }, 0
    );
    listView_DataList.setAdapter(adapter);
}

// 刷新待出库表列表
private void Refresh_ListView_OutData(Cursor cursor) {
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(
            this,
            R.layout.activity_out_storage_scan_code_out_data_listview,
            cursor,
            new String[]{"_id", "货位号", "来料日期", "库存数量", "应发数量", "扫码数量", "验证结果"},
            new int[]{
                    R.id.textView_listView_OutStorageScanCode_OutDataList_ID,
                    R.id.textView_listView_OutStorageScanCode_OutDataList_货位号,
                    // 其他UI控件ID
                    // ...
            }, 0
    );
    listView_OutDataList.setAdapter(adapter);
}

// 清空验证面板信息
private void clearValidationInfo() {
    // 重置所有验证控件
    textView_Validation_货位号A.setText("");
    textView_Validation_生产日期A.setText("");
    // 其他验证控件
    // ...
    
    // 重置扫码状态
    strCode = null;
    strHwh = null;
}
8. 循环处理
// 数据更新后的循环处理
if (Integer.parseInt(str_未扫数量) != 0) {
    // 同一货位仍有未扫数量,继续扫码
    textView_Validation_Msg.setText("此货位号还需出库:" + str_未扫数量 + ",请继续扫材料码?");
    textView_Validation_Msg.setTextColor(Color.BLUE);
    
    // 重置部分验证信息,保留货位信息
    textView_Validation_货位号B.setText("");
    textView_Validation_生产日期B.setText("");
    // 其他材料码相关控件
    // ...
    
    // 重置材料码状态
    strCode = null;
    
} else {
    // 扫码完成,重置所有验证信息
    clearValidationInfo();
    // 隐藏验证面板
    HideValidationChildLinearLayout();
}

// 重新启动扫码,等待下一次扫描
if (sm != null) {
    sm.openScan();
}

该实现采用了分层架构设计,通过DAO模式访问数据库,使用异步任务处理耗时操作,确保UI响应流畅。同时实现了条码验证、数据关联检查和数据库事务管理,保证了出库操作的准确性和数据一致性。