在SQLite中保存和显示图像

时间:2018-08-29 13:59:03

标签: android image android-sqlite

首先要注意的是,代码只适用于质量较低的图像,但是当用户以较高的质量使用手机摄像头拍摄的图像时,该图像不会显示在应用程序中。但是,较低质量的图像可以。有人可以解释为什么会这样,并且是为此编写代码的最佳方法吗?

ImageDatabaseHandler.java(仅相关代码)

public Boolean deleteItem(Integer id) {
    SQLiteDatabase db = this.getWritableDatabase();
    String table = "images";
    String whereClause = "id=?";
    String[] whereArgs = new String[]{String.valueOf(id)};
    db.delete(table, whereClause, whereArgs);
    return true;
}

public Boolean insertimage(String x, Integer i) {
    SQLiteDatabase db = this.getWritableDatabase();
    try {
        FileInputStream fs = new FileInputStream(x);       
        byte[] imgbyte = new byte[fs.available()];
        fs.read(imgbyte);
        ContentValues contentValues = new ContentValues();
        contentValues.put("id", i);
        contentValues.put("img", imgbyte);
        db.insert("images", null, contentValues);
        fs.close();
        return true;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

public Bitmap getimage(Integer id) {
    SQLiteDatabase db = this.getWritableDatabase();
    Bitmap bt = null;
    Cursor cursor = db.rawQuery("select * from images where id=?", new String[]{String.valueOf(id)});
    if (cursor.moveToNext()) {
        byte[] imag = cursor.getBlob(1);
        bt = BitmapFactory.decodeByteArray(imag, 0, imag.length);

    }
    return bt;
}

MyActivity(仅相关代码)

int stockNumber = 0;

Button insert, delImg;
EditText number;
ImageView imageView;
ImageDatabaseHandler db;
private static final int PICK_IMAGE = 100;

protected void onCreate(Bundle savedInstanceState) {
....
insert = findViewById(R.id.SetImage);
    imageView = findViewById(R.id.imageView);

    db = new ImageDatabaseHandler(this);
    insert.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_PICK, Uri.parse(
                    "content://media/internal/images/media"
            ));
            startActivityForResult(intent, PICK_IMAGE);
        }
    });

    delImg = findViewById(R.id.delImageButton);
    delImg.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startImageRemove();
        }
    });
}


protected void onStart() {
    super.onStart();

    try {
        if (db.getimage(stockNumber) != null) {
            //imageView.setImageBitmap(db.getimage(stockNumber));

imageView.setImageBitmap(Bitmap.createScaledBitmap(db.getimage(stockNumber), 500, 500, false));
        }
    } catch (NullPointerException e) {
        Toast.makeText(getApplicationContext(), "Internal database error!\nset new 
image and try again...", Toast.LENGTH_LONG).show();
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK && requestCode == PICK_IMAGE) {
        Uri uri = data.getData();
        String x = getPath(uri);

        db.deleteItem(stockNumber);
        finish();

        if (db.insertimage(x, stockNumber)) {
            Toast.makeText(getApplicationContext(), "Successful", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getApplicationContext(), "Not Successful", Toast.LENGTH_SHORT).show();
        }
    }
}

public String getPath(Uri uri) {
    if (uri == null) return null;
    String[] projection = {MediaStore.Images.Media.DATA};
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if (cursor != null) {
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }
    return uri.getPath();
}

我正在考虑一种压缩图像的方法,一旦将其从设备上的媒体存储区中选择出来,然后再将其添加到数据库中,但是我对编程和Android Studio还是一个相对较新的事物,对它的任何帮助或建议都非常值得总是:)

2 个答案:

答案 0 :(得分:0)

SqlLite对类型有限制,在您的情况下,它可能是BLOB类型。您可以在此处了解有关这些限制的更多信息:https://www.sqlite.org/limits.html

实现此目的的一种更安全的方法是将映像的路径存储在数据库中,而不是完整的位图。如果您不希望保留原始文件路径,则可以先将映像复制到“应用程序内部”文件空间,然后将该新复制的映像位置存储在数据库中。您可以在这里阅读有关文件空间的更多信息:https://developer.android.com/guide/topics/data/data-storage#filesInternal

答案 1 :(得分:0)

我能够通过使应用程序本身启动相机应用程序并以此方式设置图像质量来解决我的问题。参见下面的代码;

ImageDatabaseHandler.java(仅相关代码)

public Boolean insertimage(byte[] x, Integer i) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues contentValues = new ContentValues();

    contentValues.put("id", i);
    contentValues.put("img", x);
    db.insert("images", null, contentValues);

    return true;
}

myActivity.java(仅相关代码)

 ....
    insert = findViewById(R.id.SetImage);
    imageView = findViewById(R.id.imageView);

    db = new ImageDatabaseHandler(this);
    insert.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent photoCaptureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

            if (ActivityCompat.checkSelfPermission(getApplicationContext(),
                    Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(QuickReferenceListItem.this,
                        new String[]{Manifest.permission.CAMERA},
                        RequestCameraPermissionID);
                return;
            }
            startActivityForResult(photoCaptureIntent, requestCode);
        }
    });

 ....

 @Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 
 @NonNull int[] grantResults) {
    switch (requestCode) {
        case RequestCameraPermissionID: {

            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                if (ActivityCompat.checkSelfPermission(this,Manifest.permission.CAMERA) 
!= PackageManager.PERMISSION_GRANTED) {
                    return;
                }
                insert = findViewById(R.id.SetImage);
                imageView = findViewById(R.id.imageView);
                requestCode = 20;

                Intent photoCaptureIntent = new 
Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(photoCaptureIntent, requestCode);
            }
        }
        break;
    }
}

....

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     super.onActivityResult(requestCode, resultCode, data);
     if (this.requestCode == requestCode && resultCode == RESULT_OK) {
         Bitmap bitmap = (Bitmap) data.getExtras().get("data");

         db.deleteItem(stockNumber);
         finish();

         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
         byte[] b = baos.toByteArray();


         if (db.insertimage(b, stockNumber)) {
            Toast.makeText(getApplicationContext(), "Successful", 
 Toast.LENGTH_SHORT).show();
            } else {
               Toast.makeText(getApplicationContext(), "Not Successful", 
Toast.LENGTH_SHORT).show();
            }
       }
   }