我已经在这个问题上工作了好几天,但我无法弄清楚我做错了什么。我为一个项目制作了一个库存/商店应用程序,用户可以将他们库存的商品输入到列表中。根据我的要求,我需要给它拍照功能,我需要能够将图片保存在SQLite数据库中。那部分我已经实现了。但是当我尝试更新项目并将其再次保存到列表时,图像返回null。我附上图片以便直观地解释......
主要活动
新商品页面
将项目保存到主要活动列表视图
点击要修改的项目
除非我拍摄新照片,否则当我保存更新的项目时,图标图像将返回null
我正在使用CursorLoader。我对待图像的方式与处理数据库中所有其他列的方式相同...所以我无法弄清楚为什么它不会坚持下去。
这里是与EditorActivity中的图像有关的代码:
Bitmap photos;
// Content URI for the existing item (null if it's a new item)
private Uri mCurrentItemUri;
// Picture taking capability with button
public void takePicture(View view) {
PackageManager pm = this.getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
} else {
Toast.makeText(EditorActivity.this, "Sorry! You don't have a camera app.", Toast.LENGTH_SHORT).show();
}
}
// Once image is taken, save to image view and then save to db as a ByteArray
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
photos = (Bitmap) extras.get("data");
mImageView.setImageBitmap(photos);
}
}
// Get user input from editor and save item into database.
private void saveItem() {
// Read from input fields
// Use trim to eliminate leading or trailing white space
String nameString = mNameEditText.getText().toString().trim();
String priceString = mPriceEditText.getText().toString().trim();
// Find quantity TV by id and extract int value as String
TextView quantityTextView = (TextView) findViewById(R.id.quantity_editor_text_view);
String quantityString = quantityTextView.getText().toString();
ImageView iconImage = (ImageView) findViewById(R.id.image_view_editor);
// Check if this is supposed to be a new item and check if all the fields in the editor are blank
if (mCurrentItemUri == null && TextUtils.isEmpty(nameString)
&& TextUtils.isEmpty(priceString) && TextUtils.isEmpty(quantityString) && iconImage == null) {
// Since no fields were modified, we can return early without creating a new item.
// No need to create ContentValues and no need to do any ContentProvider operations.
return;
}
// Create a ContentValues object where column names are the keys and item attributes from the editor are the values.
ContentValues values = new ContentValues();
// Find image by the member variable "photos" and get the bytes
byte[] bytes = Utils.getImageBytes(photos);
values.put(ItemEntry.IMAGE_VIEW, bytes);
values.put(ItemEntry.COLUMN_NAME, nameString);
int price = 0;
if (!TextUtils.isEmpty(priceString)) {
price = Integer.parseInt(priceString);
}
values.put(ItemEntry.COLUMN_PRICE, price);
values.put(ItemEntry.COLUMN_QUANTITY, quantityString);
// Determine if this is a new or existing item by checking if mCurrentItemUri is null or not
if (mCurrentItemUri == null) {
// This is a NEW item, so insert a new item into the provider,
// returning the content URI for the new item.
Uri newUri = getContentResolver().insert(ItemEntry.CONTENT_URI, values);
// Show a toast message depending on whether or not the insertion was successful.
if (newUri == null) {
// If the new content URI is null, then there was an error with insertion.
Toast.makeText(this, getString(R.string.insert_item_failed), Toast.LENGTH_SHORT).show();
} else {
// Otherwise, the insertion was successful and we can display a toast.
Toast.makeText(this, getString(R.string.insert_item_successful), Toast.LENGTH_SHORT).show();
}
} else {
// Otherwise this is an EXISTING item, so update the item with content URI: mCurrentItemUri
// and pass in the new ContentValues. Pass in null for the selection and selection args
// because mCurrentItemUri will already identify the correct row in the database that
// we want to modify.
int rowsAffected = getContentResolver().update(mCurrentItemUri, values, null, null);
// Show a toast message depending on whether or not the update was successful.
if (rowsAffected == 0) {
// If no rows were affected, then there was an error with the update.
Toast.makeText(this, getString(R.string.edit_item_failed), Toast.LENGTH_SHORT).show();
} else {
// Otherwise, the update was successful and we can display a toast.
Toast.makeText(this, getString(R.string.edit_item_successful), Toast.LENGTH_SHORT).show();
}
}
}
用于图像方法的Utils文件:
public class Utils {
// Used in saveItem
// Adding the if/else statement here allows the picture to be null
// But now the picture disappears when you update an item without taking a new pic.
public static byte[] getImageBytes(Bitmap bitmap) {
if (bitmap != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
} else {
return null;
}
}
// Used in OnLoadFinished (Editor) and cursor adapter
public static Bitmap getImage(byte[] image) {
return BitmapFactory.decodeByteArray(image, 0, image.length);
}
}
我相当肯定问题出在saveItem方法中,但如果您想查看整个文件,请告诉我。
答案 0 :(得分:0)
这项工作的最佳方法是,您应该将图像保存在手机目录中,该目录可根据您的要求从图库中访问/无法访问,并将文件路径保存在图像列中,您可以在需要时访问该图像加载。我也在我的一个离线应用程序中遵循相同的方法,它可以顺利运行但没有任何问题,但确保无论何时执行任何行的删除选项,那么您还应该删除该文件以便更好地进行存储管理。
答案 1 :(得分:0)
发布以防万一。问题不在我想象的地方。在EditorActivity的onLoadFinished方法中,我需要添加以下行:
photos = Utils.getImage(image);
从光标获取blob后。这样可以在更新项目后保留图片,而无需拍摄新照片。
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// Bail early if the cursor is null or there is less than 1 row in the cursor
if (cursor == null || cursor.getCount() < 1) {
return;
}
// Proceed with moving to the first row of the cursor and reading data from it
// (This should be the only row in the cursor)
if (cursor.moveToFirst()) {
// Find the columns of item attributes that we're interested in
int imageColumnIndex = cursor.getColumnIndex(ItemEntry.IMAGE_VIEW);
int nameColumnIndex = cursor.getColumnIndex(ItemEntry.COLUMN_NAME);
int priceColumnIndex = cursor.getColumnIndex(ItemEntry.COLUMN_PRICE);
int quantityColumnIndex = cursor.getColumnIndex(ItemEntry.COLUMN_QUANTITY);
// Extract out the value from the Cursor for the given column index
byte[] image = cursor.getBlob(imageColumnIndex);
// populate the photos variable with bytes and the picture will save to the list view after editing item
photos = Utils.getImage(image);
String name = cursor.getString(nameColumnIndex);
String price = cursor.getString(priceColumnIndex);
int quantity = cursor.getInt(quantityColumnIndex);
// Update the views on the screen with the values from the database
// if I delete the if/else statement, error saying Attempt to get length of null array from method Utils.getImage
// can remove once I get image to stick
if (image != null) {
mImageView.setImageBitmap(Utils.getImage(image));
} else {
mImageView.setImageBitmap(null);
}
mNameEditText.setText(name);
mPriceEditText.setText(price);
mQuantityTextView.setText(Integer.toString(quantity));
}
}