You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在SQLite中保存图片路径并实现路径检索?

没问题,我帮你梳理下怎么把Blob存储改成路径存储,这样既能保证图片质量,又能实现路径检索~

解决方案:从Blob存储改为图片路径存储

一、修改数据库表结构

首先得把原来存储Blob的字段换成文本类型来存路径。如果是新建表,直接调整建表语句;如果是已有数据库,要写升级逻辑避免数据丢失:

1. 新建表语句

CREATE TABLE photos (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    image_path TEXT NOT NULL  -- 替换原来的image BLOB字段
);

2. 数据库升级逻辑(针对已有数据库)

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion < 2) {
        // 添加image_path字段
        db.execSQL("ALTER TABLE photos ADD COLUMN image_path TEXT;");
        // 可选:如果要迁移旧Blob数据,可以把Blob转成图片保存到本地,再写入路径
    }
}

二、调整拍照与存储逻辑

原来的代码是把拍照后的图片转成Blob存库,现在要改成先把图片保存到本地,再存路径:

1. 创建本地存储文件(避免权限问题)

private String mCurrentPhotoPath;

private File createImageFile() throws IOException {
    // 生成唯一文件名,避免重复
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    // 用应用专属图片目录,Android 10+无需额外权限,卸载应用时会自动删除
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File imageFile = File.createTempFile(imageFileName, ".jpg", storageDir);
    // 保存绝对路径,后续存入数据库
    mCurrentPhotoPath = imageFile.getAbsolutePath();
    return imageFile;
}

2. 启动拍照Intent(配置FileProvider避免Uri异常)

private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            // 处理文件创建失败的情况
            ex.printStackTrace();
        }
        if (photoFile != null) {
            // 用FileProvider生成安全Uri(Android 7+必须)
            Uri photoURI = FileProvider.getUriForFile(this,
                    "com.yourpackage.fileprovider",  // 替换成你的应用包名+fileprovider
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            startActivityForResult(takePictureIntent, CAPTURE_PHOTO);
        }
    }
}

注意:需要在AndroidManifest.xml中配置FileProvider:

<application>
    ...
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.yourpackage.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

然后在res/xml下创建file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="my_images" path="Pictures" />
</paths>

3. 处理拍照结果,存入路径到数据库

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CAPTURE_PHOTO && resultCode == RESULT_OK) {
        // 将图片路径插入数据库
        ContentValues values = new ContentValues();
        values.put("image_path", mCurrentPhotoPath);
        // 假设你有SQLiteDatabase实例db
        db.insert("photos", null, values);
        // 刷新Loader更新列表
        getSupportLoaderManager().restartLoader(0, null, this);
    }
}

三、实现路径检索与图片加载

调整Loader的查询逻辑,拿到路径后加载图片:

1. 调整Loader查询字段

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // 只查询需要的字段,替换原来的Blob字段
    String[] projection = {"id", "image_path"};
    return new CursorLoader(this,
            // 替换成你的ContentUri或直接用数据库查询
            PhotoContentProvider.CONTENT_URI,
            projection,
            null,
            null,
            null);
}

2. 加载图片到界面

推荐用Glide/Picasso等图片加载库,避免OOM:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    while (data.moveToNext()) {
        String imagePath = data.getString(data.getColumnIndexOrThrow("image_path"));
        File imageFile = new File(imagePath);
        if (imageFile.exists()) {
            // 用Glide加载图片到ImageView
            Glide.with(this)
                 .load(imageFile)
                 .placeholder(R.drawable.default_photo)  // 占位图
                 .into(yourTargetImageView);
        } else {
            // 处理文件丢失的情况,比如显示错误图
        }
    }
}

四、关键注意事项

  • 权限适配:Android 10+用应用专属目录无需WRITE_EXTERNAL_STORAGE权限;如果要存公共目录,需用MediaStore或申请权限。
  • 文件有效性:查询路径后要判断文件是否存在,避免因文件被删除导致加载失败。
  • 图片清理:应用专属目录的图片会随应用卸载删除,如需永久保存可考虑公共目录或云存储。

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

火山引擎 最新活动