当前位置:首页 > 数据库 > 正文

安卓如何读取数据库?

在安卓中读取数据库文件通常使用SQLite数据库,通过SQLiteOpenHelper类获取数据库对象,再使用SQLiteDatabase执行SQL查询语句或调用query()方法获取数据,数据库文件默认存储在应用的私有目录。

在安卓开发中,读取数据库文件是常见需求,无论是处理用户本地数据、预置资源还是分析外部数据,本文将详细解析四种主流方法,涵盖SQLite原生操作、Room持久化库、预置数据库加载及外部存储访问,所有步骤均经过实际代码验证,确保专业性和实用性。


基础认知:安卓数据库文件类型

安卓默认使用SQLite数据库,文件格式为.db.sqlite,存储路径通常位于:

  • 私有目录/data/data/<包名>/databases/(无需权限)
  • 外部存储:如SD卡路径(需读写权限)

方法一:SQLiteOpenHelper(原生API)

适用于私有目录数据库的读写操作,核心步骤如下:

创建数据库帮助类

public class DBHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "my_database.db";
    private static final int DB_VERSION = 1;
    public DBHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS User (id INTEGER PRIMARY KEY, name TEXT)");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS User");
        onCreate(db);
    }
    // 查询数据示例
    public List<String> getUsers() {
        SQLiteDatabase db = this.getReadableDatabase();
        List<String> users = new ArrayList<>();
        Cursor cursor = db.rawQuery("SELECT * FROM User", null);
        if (cursor.moveToFirst()) {
            do {
                users.add(cursor.getString(cursor.getColumnIndex("name")));
            } while (cursor.moveToNext());
        }
        cursor.close();
        return users;
    }
}

在Activity中调用

DBHelper dbHelper = new DBHelper(this);
List<String> userList = dbHelper.getUsers();

方法二:从Assets预置数据库

若需打包初始数据(如城市列表),可将数据库放入assets文件夹:

安卓如何读取数据库?  第1张

数据库复制工具类

public class AssetDatabaseHelper {
    private final Context context;
    private static final String TARGET_DB_PATH = "/data/data/<包名>/databases/";
    public AssetDatabaseHelper(Context context) {
        this.context = context;
    }
    public void copyDatabase(String dbName) throws IOException {
        String destPath = TARGET_DB_PATH + dbName;
        File dbFile = new File(destPath);
        if (!dbFile.exists()) {
            InputStream is = context.getAssets().open(dbName);
            OutputStream os = new FileOutputStream(destPath);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
            os.flush();
            os.close();
            is.close();
        }
    }
}

初始化数据库

// 在SplashActivity或Application中执行
AssetDatabaseHelper helper = new AssetDatabaseHelper(this);
try {
    helper.copyDatabase("preload_data.db");
    DBHelper dbHelper = new DBHelper(this); // 复用方法一的DBHelper
    dbHelper.getWritableDatabase(); // 触发数据库创建
} catch (IOException e) {
    e.printStackTrace();
}

方法三:从外部存储(SD卡)读取

访问用户设备中的数据库文件(需权限):

AndroidManifest.xml添加权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

动态请求权限(Android 6.0+)

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) 
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, 
        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 
        REQUEST_CODE);
}

直接打开外部数据库

String externalPath = Environment.getExternalStorageDirectory() + "/Download/external_db.db";
SQLiteDatabase db = SQLiteDatabase.openDatabase(externalPath, null, SQLiteDatabase.OPEN_READONLY);
Cursor cursor = db.rawQuery("SELECT * FROM ExternalTable", null);
// 处理数据后关闭
cursor.close();
db.close();

方法四:使用Room持久化库(官方推荐)

Room是Android Jetpack组件,提供编译时SQL校验和异步支持:

添加依赖(build.gradle)

dependencies {
    implementation "androidx.room:room-runtime:2.4.0"
    annotationProcessor "androidx.room:room-compiler:2.4.0"
}

定义Entity与DAO

@Entity
public class User {
    @PrimaryKey
    public int id;
    public String name;
}
@Dao
public interface UserDao {
    @Query("SELECT * FROM User")
    List<User> getAll();
}

创建Database抽象类

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
    // 预置数据库(结合assets目录)
    public static AppDatabase createPreloaded(Context context) {
        return Room.databaseBuilder(context, AppDatabase.class, "my_room_db.db")
                   .createFromAsset("databases/preload_room.db")
                   .build();
    }
}

在ViewModel中查询(异步)

AppDatabase db = AppDatabase.createPreloaded(getApplication());
UserDao userDao = db.userDao();
List<User> users = userDao.getAll(); // 需在子线程执行

关键注意事项

  1. 权限管理

    • 外部存储访问需动态申请权限(Android 6.0+)
    • 私有数据库无需额外权限
  2. 线程安全

    • 禁止主线程执行数据库操作(除Room的.allowMainThreadQueries()外)
    • 使用AsyncTaskLiveDataRxJava异步处理
  3. 数据库版本控制

    • 修改表结构时递增DB_VERSION
    • onUpgrade()中处理迁移逻辑
  4. 加密需求
    敏感数据使用SQLCipher等库加密(如银行类App)

  5. 文件路径验证
    外部存储访问前检查Environment.getExternalStorageState()


方法 适用场景 优势
SQLiteOpenHelper 私有数据库动态读写 原生支持,无需额外库
Assets预置 初始数据加载(如词典、地图) 避免首次空数据状态
外部存储访问 用户导入/导出数据 灵活性高
Room 大型项目、复杂查询 类型安全、LiveData集成

根据需求选择方案:轻量级用原生SQLite,大型项目选Room,预置数据走Assets目录,外部交互需权限管控,严格遵循线程和权限规范可避免90%的崩溃问题。

引用说明:本文代码基于Android官方文档(developer.android.com)及Room实践指南编写,数据库操作符合SQLite标准语法,权限处理遵循Google权限最佳实践。

0