You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:零基础开发Android条码扫描并即时存入SQL数据库的APP

从零开始做Android扫码存SQL APP的完整指南

嘿,完全理解你的处境——从零碰Android开发,还找不到精准的教程,确实头大。不过你的需求其实很典型,我把整个流程拆成超级易懂的步骤,跟着走就能搞定!

第一步:搞定开发环境

首先下载安装最新版的Android Studio,安装过程中默认选Android SDK就行(不用纠结太多选项,新手默认配置足够)。打开后创建一个Empty Activity项目,语言选Kotlin(比Java简洁,入门更快),项目名随便取,比如BarcodeScannerDB。

第二步:集成扫码功能(不用自己写!)

咱们直接用成熟的扫码库zxing-android-embedded,省得自己造轮子。

  1. 打开模块级的build.gradle(注意是Module: app那个文件),在dependencies里加一行:

    implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
    implementation 'com.google.zxing:core:3.4.1'
    

    然后点击Sync Now同步依赖。

  2. 给你的主Activity加一个扫码按钮和显示结果的文本框,布局文件activity_main.xml大概这样:

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp">
    
        <Button
            android:id="@+id/scanBtn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="扫描条码"/>
    
        <TextView
            android:id="@+id/resultTv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:textSize="18sp"/>
    
    </LinearLayout>
    
  3. 处理扫码逻辑:在MainActivity.kt里,先申请相机权限(Android 6.0以上必须动态申请),然后点击按钮启动扫码界面:

    import android.Manifest
    import android.content.Intent
    import android.content.pm.PackageManager
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.widget.Button
    import android.widget.TextView
    import androidx.core.app.ActivityCompat
    import androidx.core.content.ContextCompat
    import com.journeyapps.barcodescanner.ScanContract
    import com.journeyapps.barcodescanner.ScanOptions
    
    class MainActivity : AppCompatActivity() {
        private lateinit var resultTv: TextView
        // 扫码契约(新版ZXing推荐用这个,替代旧的onActivityResult)
        private val barcodeLauncher = registerForActivityResult(ScanContract()) { result ->
            if (result.contents != null) {
                val barcodeContent = result.contents
                resultTv.text = "扫描结果:$barcodeContent"
                // 这里后面会加存数据库的代码
            }
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            resultTv = findViewById(R.id.resultTv)
            val scanBtn = findViewById<Button>(R.id.scanBtn)
    
            scanBtn.setOnClickListener {
                // 先检查相机权限
                if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED
                ) {
                    // 申请权限
                    ActivityCompat.requestPermissions(
                        this,
                        arrayOf(Manifest.permission.CAMERA),
                        100
                    )
                } else {
                    // 权限已通过,启动扫码
                    startScan()
                }
            }
        }
    
        // 处理权限申请结果
        override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<out String>,
            grantResults: IntArray
        ) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
            if (requestCode == 100 && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startScan()
            }
        }
    
        // 启动扫码界面的方法
        private fun startScan() {
            val options = ScanOptions()
            options.setPrompt("对准条码进行扫描")
            options.setBeepEnabled(true) // 扫码成功响铃
            barcodeLauncher.launch(options)
        }
    }
    

    现在运行APP,点击按钮就能扫码并显示结果了!

第三步:集成本地SQL数据库(用Room,比原生SQLite简单10倍)

Android官方推荐用Room Persistence Library,封装了SQLite,不用写复杂的SQL语句。

  1. 先加Room的依赖,还是在模块级build.gradle的dependencies里:

    // Room
    implementation "androidx.room:room-runtime:2.5.2"
    kapt "androidx.room:room-compiler:2.5.2"
    // 如果用Kotlin协程的话,再加这个(推荐,避免主线程操作数据库)
    implementation "androidx.room:room-ktx:2.5.2"
    

    注意顶部要加kapt插件:在plugins块里加id 'kotlin-kapt',然后Sync Now。

  2. 定义数据库实体(对应数据库的表):新建一个BarcodeData.kt文件:

    import androidx.room.Entity
    import androidx.room.PrimaryKey
    
    @Entity(tableName = "barcode_table")
    data class BarcodeData(
        @PrimaryKey(autoGenerate = true) val id: Int = 0,
        val content: String, // 条码内容
        val timestamp: Long // 扫描时间戳
    )
    
  3. 定义Dao(数据访问对象,用来操作数据库):新建BarcodeDao.kt:

    import androidx.room.Dao
    import androidx.room.Insert
    import androidx.room.Query
    
    @Dao
    interface BarcodeDao {
        // 插入一条条码数据
        @Insert
        suspend fun insertBarcode(barcode: BarcodeData)
    
        // 可选:查询所有条码数据,方便测试
        @Query("SELECT * FROM barcode_table ORDER BY timestamp DESC")
        suspend fun getAllBarcodes(): List<BarcodeData>
    }
    
  4. 创建数据库类:新建AppDatabase.kt:

    import androidx.room.Database
    import androidx.room.Room
    import androidx.room.RoomDatabase
    import android.content.Context
    
    @Database(entities = [BarcodeData::class], version = 1)
    abstract class AppDatabase : RoomDatabase() {
        abstract fun barcodeDao(): BarcodeDao
    
        // 单例模式,避免重复创建数据库实例
        companion object {
            @Volatile
            private var INSTANCE: AppDatabase? = null
    
            fun getInstance(context: Context): AppDatabase {
                return INSTANCE ?: synchronized(this) {
                    val instance = Room.databaseBuilder(
                        context.applicationContext,
                        AppDatabase::class.java,
                        "barcode_database"
                    ).build()
                    INSTANCE = instance
                    instance
                }
            }
        }
    }
    
  5. 把扫码结果存入数据库:回到MainActivity.kt,修改扫码成功后的逻辑,用协程操作数据库(避免主线程阻塞):
    首先加协程依赖(如果之前没加的话):

    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
    

    然后修改barcodeLauncher的代码:

    private val barcodeLauncher = registerForActivityResult(ScanContract()) { result ->
        if (result.contents != null) {
            val barcodeContent = result.contents
            resultTv.text = "扫描结果:$barcodeContent"
            // 存数据库
            val barcodeData = BarcodeData(content = barcodeContent, timestamp = System.currentTimeMillis())
            // 用协程在后台执行
            lifecycleScope.launch {
                val dao = AppDatabase.getInstance(this@MainActivity).barcodeDao()
                dao.insertBarcode(barcodeData)
                // 可选:提示用户已保存
                runOnUiThread {
                    resultTv.text = "扫描结果:$barcodeContent\n已保存到数据库"
                }
            }
        }
    }
    

第四步:测试验证

现在运行APP,扫描几个条码,然后可以加个按钮来查询所有数据(可选),比如在布局里加个按钮:

<Button
    android:id="@+id/viewBtn"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:text="查看已存条码"/>

然后在MainActivity.kt里加点击事件:

val viewBtn = findViewById<Button>(R.id.viewBtn)
viewBtn.setOnClickListener {
    lifecycleScope.launch {
        val dao = AppDatabase.getInstance(this@MainActivity).barcodeDao()
        val allBarcodes = dao.getAllBarcodes()
        // 在UI线程显示结果
        runOnUiThread {
            val sb = StringBuilder()
            allBarcodes.forEach {
                sb.append("ID: ${it.id}, 内容: ${it.content}, 时间: ${it.timestamp}\n")
            }
            resultTv.text = sb.toString()
        }
    }
}

新手必看提示

  • 一定要用真机测试,模拟器的相机可能不好用,甚至没有相机;
  • 遇到报错先看Android Studio底部的Logcat,红色的错误信息里会告诉你哪里出问题了;
  • 不用追求完美,先让扫码和存数据跑通,再慢慢优化界面和功能;
  • Room的版本如果有更新,可以换成最新的,只要保持runtime和compiler版本一致就行。

内容的提问来源于stack exchange,提问作者Tolga20

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:41:22