0

我正在尝试制作一个应用程序,我可以在其中导入图片,添加一些详细信息,然后将此信息保存到设备上的 SQLite 数据库中。在将详细信息添加到数据库之前,我将图像压缩并保存到设备中。当我从相机中选择一个大图像时遇到问题,它会导致数据库锁定?但是,当保存没有图像的详细信息时,它会成功。请看我下面的代码和错误:

数据库:

public class DatabaseHandler extends SQLiteOpenHelper {

// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;

// Database Name
private static final String DATABASE_NAME = "showcaseManager";

// Showcase table name
private static final String TABLE_SHOWCASE = "showcase";

// Showcase Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
private static final String KEY_DESCRIPTION = "description";
private static final String KEY_IMAGE = "image";
private static final String KEY_RATING = "rating";

private static DatabaseHandler mInstance = null;

public static String Lock = "dblock";

public static DatabaseHandler getInstance() {
    if (mInstance == null) {
        mInstance = new DatabaseHandler();
    }
    return mInstance;
}

private DatabaseHandler() {
    super(MainActivity.getContext(), DATABASE_NAME, null, DATABASE_VERSION);
}

// Creating Tables
@Override
public void onCreate(SQLiteDatabase db) {
    String CREATE_SHOWCASE_TABLE = "CREATE TABLE " + TABLE_SHOWCASE + "("
            + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
            + KEY_DESCRIPTION + " TEXT," + KEY_IMAGE + " TEXT," + KEY_RATING + " TEXT" + ")";
    db.execSQL(CREATE_SHOWCASE_TABLE);
}

// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // Drop older table if existed
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_SHOWCASE);

    // Create tables again
    onCreate(db);
}

/**
 * All CRUD(Create, Read, Update, Delete) Operations
 */

// Adding new item. ##Correct##
public void addItem(ShowcaseItemLite item) {
    Log.v("Database", "Adding Item 1/2: " + item.getName());

    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_NAME, item.getName()); // Item Name
    values.put(KEY_DESCRIPTION, item.getDescription()); // Item Description
    values.put(KEY_IMAGE, item.getCompressedImagePath()); // Item Image Path
    values.put(KEY_RATING, item.getRating()); // Item Rating

    // Inserting Row
    db.insert(TABLE_SHOWCASE, null, values);
    db.close(); // Closing database connection
    Log.v("Database", "Item added 2/2.");
}

// Getting single item. ##Correct##
public ShowcaseItemLite getItem(int id) {
    Log.v("Database", "Getting item 1/2: " + id);
    SQLiteDatabase db = this.getReadableDatabase();

    Cursor cursor = db.query(TABLE_SHOWCASE, new String[] { KEY_ID,
            KEY_NAME, KEY_DESCRIPTION, KEY_IMAGE, KEY_RATING }, KEY_ID + "=?",
            new String[] { String.valueOf(id) }, null, null, null, null);
    if (cursor != null)
        cursor.moveToFirst();

    ShowcaseItemLite item = new ShowcaseItemLite(Integer.parseInt(cursor.getString(0)));
    item.setName(cursor.getString(1));
    item.setDescription(cursor.getString(2));
    item.setImagePath(cursor.getString(3));
    item.setRating(Float.valueOf(cursor.getString(4)));

    Log.v("Database", "Item Got 2/2: " + cursor.getString(1));

    // return item
    return item;
}

// Getting All Items. ##Correct##
public List<ShowcaseItemLite> getAllItems() {
    Log.v("Database", "Getting all items 1/2.");
    List<ShowcaseItemLite> itemList = new ArrayList<ShowcaseItemLite>();
    // Select All Query
    String selectQuery = "SELECT  * FROM " + TABLE_SHOWCASE;

    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (cursor.moveToFirst()) {
        do {
            ShowcaseItemLite item = new ShowcaseItemLite(Integer.parseInt(cursor.getString(0)));
            item.setName(cursor.getString(1));
            item.setDescription(cursor.getString(2));
            item.setCompressedImagePath(cursor.getString(3));
            item.setRating(Float.valueOf(cursor.getString(4)));

            // Adding Item to list
            itemList.add(item);
        } while (cursor.moveToNext());
    }

    Log.v("Database", "Received all items 2/2. Amount: " + itemList.size());
    // return item list
    return itemList;
}

// Updating single item. ##Correct##
public int updateItem(ShowcaseItemLite item) {
    Log.v("Database", "Updating Item 1/2: " + item.getName());

    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_NAME, item.getName());
    values.put(KEY_DESCRIPTION, item.getDescription());
    values.put(KEY_IMAGE, item.getImagePath());

    // updating row
    int i = db.update(TABLE_SHOWCASE, values, KEY_ID + " = ?",
            new String[] { String.valueOf(item.getDatabaseID()) });

    db.close();

    Log.v("Database", "Item Updated 2/2");

    return i;
}

// Deleting single item
public void deleteItem(ShowcaseItemLite item) {
    synchronized(Lock) {
        Log.v("Database", "Deleting Item 1/2: " + item.getName());
        SQLiteDatabase db = this.getWritableDatabase();

        db.delete(TABLE_SHOWCASE, KEY_ID + " = ?",
                new String[] { String.valueOf(item.getDatabaseID()) });
        db.close();
        Log.v("Database", "Item deleted 2/2: ");
    }
}


// Getting items Count
public int getItemCount() {
    Log.v("Database", "Preparing to get Item Count 1/2. ");
    String countQuery = "SELECT  * FROM " + TABLE_SHOWCASE;
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.rawQuery(countQuery, null);
    int count = cursor.getCount();
    cursor.close();

    Log.v("Database", "Received item count 2/2: " + count);

    // return count
    return count;
}
}

物品类别:

public class ShowcaseItemLite {

private String name;
private String description;
private String imagePath;
private float rating;
private String file_path = MainActivity.getStorageFilePath();
private int databaseID = 0;
private String thumbnailStoredLoc;
private String compressedImageStoredLoc;

public ShowcaseItemLite(int databaseID){
    this.setDatabaseID(databaseID);
}

public ShowcaseItemLite(String name, String description, String imagePath, float rating){
    this.name = name;
    this.description = description;
    this.imagePath = imagePath;
    this.rating = rating;

}

public String getName(){
    return name;
}

public String getDescription(){
    return description;
}

public String getImagePath(){
    return imagePath;
}

public float getRating(){
    return rating;
}

public int getDatabaseID() {
    return databaseID;
}

public void setDatabaseID(int databaseID) {
    this.databaseID = databaseID;
}

public String getFile_path() {
    return file_path;
}

public void setFile_path(String file_path) {
    this.file_path = file_path;
}

public void setName(String name) {
    this.name = name;
}

public void setDescription(String description) {
    this.description = description;
}

public void setImagePath(String imagePath) {
    this.imagePath = imagePath;
}

public void setRating(float rating) {
    this.rating = rating;
}


public void saveImageAndThumb(int imageID){
    Log.v("IMAGE_SAVE_LOG", "Preparing to store images.");
    if(imagePath != null && !imagePath.equals("")){
        try{
            File dir = new File(file_path);
            if(!dir.exists()){
                dir.mkdirs();
            }
            File file = new File(dir, "I"+imageID+".bmp");
            if(!file.exists()){

                FileOutputStream fOut = new FileOutputStream(file);

                Bitmap bitmap = shrinkBitmap(imagePath);
                bitmap.compress(Bitmap.CompressFormat.PNG, 85, fOut);
                fOut.flush();
                fOut.close();
                //bitmap.recycle();

                this.compressedImageStoredLoc = file.getAbsolutePath().toString();
                Log.v("IMAGE_SAVE_LOG", "Saved image path: " + compressedImageStoredLoc);
            }else{
                Log.v("IMAGE_SAVE_LOG", "Image exists. Skipping creation: " + file.toString());
                this.compressedImageStoredLoc = file.getAbsolutePath().toString();
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try{
            File dir = new File(file_path);
            if(!dir.exists()){
                dir.mkdirs();
            }
            File file = new File(dir, "T"+imageID+".bmp");
            if(!file.exists()){
                FileOutputStream fOut = new FileOutputStream(file);

                Bitmap bitmap = shrinkBitmapToThumb(imagePath);
                bitmap.compress(Bitmap.CompressFormat.PNG, 85, fOut);
                fOut.flush();
                fOut.close();

                this.thumbnailStoredLoc = file.getAbsolutePath().toString();
            }else{
                Log.v("IMAGE_SAVE_LOG", "Thumbnail exists. Skipping creation: " + file.toString());
                this.thumbnailStoredLoc = file.getAbsolutePath().toString();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }   
}

private Bitmap shrinkBitmap(String file){
    int height = 200;
    int width = 200;

    BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
    bmpFactoryOptions.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);

    int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
    int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);

    if (heightRatio > 1 || widthRatio > 1)
    {
        if (heightRatio > widthRatio)
        {
            bmpFactoryOptions.inSampleSize = heightRatio;
        } else {
            bmpFactoryOptions.inSampleSize = widthRatio; 
        }
    }

    bmpFactoryOptions.inJustDecodeBounds = false;
    bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);
    return bitmap;
}

private Bitmap shrinkBitmapToThumb(String file){
    int height = 100;
    int width = 100;

    BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
    bmpFactoryOptions.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);

    int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
    int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);

    if (heightRatio > 1 || widthRatio > 1)
    {
        if (heightRatio > widthRatio)
        {
            bmpFactoryOptions.inSampleSize = heightRatio;
        } else {
            bmpFactoryOptions.inSampleSize = widthRatio; 
        }
    }

    bmpFactoryOptions.inJustDecodeBounds = false;
    bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);
    return bitmap;
}

public String getImageThumbnailPath() {
    if(thumbnailStoredLoc == null){
        if(compressedImageStoredLoc != null){
            return getCompressedImagePath().replace("I", "T");
        }else{
            return null;
        }   
    }else{
        return thumbnailStoredLoc;
    }
}

public String setImageThumbnailPath() {
    return thumbnailStoredLoc;
}

public String getCompressedImagePath() {
    return compressedImageStoredLoc;
}

public void setCompressedImagePath(String image) {
    this.compressedImageStoredLoc = image;
}
}

新物品类别:

public class NewItemActivity extends Activity {

private static final int SELECT_PICTURE = 0;
public static int TAKE_IMAGE = 111;
private String selectedImagePath = null;
private ImageView imageView;
private String selectedCameraPath;
private int itemID;

public NewItemActivity() {

}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_new_item);

    imageView = (ImageView)findViewById(R.id.newItemImageView);

    Bundle extras = getIntent().getExtras();
    itemID = extras.getInt("newID");
    Log.v("IMAGE_SAVE_LOG", "New ImageID: " + itemID);

    Button galleryButton =((Button) findViewById(R.id.galleryButton));

    galleryButton.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,"Select Picture"), SELECT_PICTURE);
        }
    });

    Button cameraButton =((Button) findViewById(R.id.cameraButton));

    cameraButton.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            Intent intent = new Intent(NewItemActivity.this, CameraActivity.class);
            NewItemActivity.this.startActivity(intent);
        }        
    });

    Button saveButton =((Button) findViewById(R.id.saveButton));

    saveButton.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            EditText nameTextField = (EditText) findViewById(R.id.nameTextField);
            String nameTextFieldString = nameTextField.getText().toString();
            EditText descriptionTextField = (EditText) findViewById(R.id.descriptionTextField);
            String descriptionTextFieldString = descriptionTextField.getText().toString();
            RatingBar rating = (RatingBar) findViewById(R.id.newRatingbar);

            Log.v("IMAGE_SAVE_LOG", "SelectedImagePath: " + selectedImagePath);

            if(!nameTextFieldString.equals("")){
                if(descriptionTextFieldString.equals("")){
                    Log.v("IMAGE_SAVE_LOG", "Creating Item 1/3." + "ItemID: " + itemID);
                    ShowcaseItemLite item = new ShowcaseItemLite(nameTextFieldString,"No Description.",selectedImagePath,rating.getRating());
                    item.saveImageAndThumb(itemID);
                    Log.v("IMAGE_SAVE_LOG", "Item created 2/3.");
                    DatabaseHandler.getInstance().addItem(item);
                    Log.v("IMAGE_SAVE_LOG", "Item added 3/3.");
                    finish();
                }else{
                    Log.v("IMAGE_SAVE_LOG", "Creating Item 1/3.");
                    ShowcaseItemLite item = new ShowcaseItemLite(nameTextFieldString, descriptionTextFieldString, selectedImagePath, rating.getRating());
                    item.saveImageAndThumb(itemID);
                    Log.v("IMAGE_SAVE_LOG", "Item created 2/3.");
                    DatabaseHandler.getInstance().addItem(item);
                    Log.v("IMAGE_SAVE_LOG", "Item added 3/3.");
                    finish();
                }
            }
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.new_item, menu);
    return true;
}

 public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath  = getPath(selectedImageUri);
                imageView.setImageURI(selectedImageUri);
            }
        }

        if (resultCode == RESULT_OK && requestCode == TAKE_IMAGE){
            String cameraPath = data.getStringExtra("location");
            Log.v("IMAGE_SAVE_LOG", "Camera image location: " + cameraPath);
            selectedCameraPath = cameraPath;
            //imageView.setImageURI(cameraPath);
        }
    }

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

堆栈跟踪:

11-09 20:34:42.610: E/AndroidRuntime(8970): FATAL EXCEPTION: main
11-09 20:34:42.610: E/AndroidRuntime(8970): java.lang.NullPointerException
11-09 20:34:42.610: E/AndroidRuntime(8970):     at     android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at     android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at     database.DatabaseHandler.addItem(DatabaseHandler.java:77)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at     showcasen.NewItemActivity$3.onClick(NewItemActivity.java:84)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at     android.view.View.performClick(View.java:4211)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at     android.view.View$PerformClick.run(View.java:17267)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at android.os.Handler.handleCallback(Handler.java:615)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at android.os.Handler.dispatchMessage(Handler.java:92)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at android.os.Looper.loop(Looper.java:137)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at android.app.ActivityThread.main(ActivityThread.java:4898)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at java.lang.reflect.Method.invokeNative(Native Method)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at java.lang.reflect.Method.invoke(Method.java:511)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
11-09 20:34:42.610: E/AndroidRuntime(8970):     at dalvik.system.NativeStart.main(Native Method)
4

3 回答 3

0

在几种方法(getItemgetAllItems等)中,您打开一个数据库连接,然后不关闭它。确保在打开后始终将其关闭。

更好的是,在启动时只打开一次,并在应用程序的整个生命周期内重复使用相同的连接。

于 2013-11-09T21:17:36.650 回答
0

我有一个类似的问题。确保您插入的图像不大。我发现我的图像大约 6MB !而分贝不喜欢这样。您想尝试使图像大小达到 0.3 MB (300 KB) 左右。

您可以通过在图像字节上调用此代码来找到它

someImageBytes.length
于 2014-01-30T11:35:10.780 回答
0

堆栈跟踪说传递给的上下文SQLiteOpenHelper为空。

你好像从MainActivity.getContext()那里经过。那是不对的。在需要数据库的地方传入有效的上下文。例如, inNewItemActivity可以是NewItemActivity.this甚至getApplicationContext()

另请注意,您只能将活动、服务或应用程序用作上下文onCreate(),而不是更早。

为什么会出现大图像是因为应用程序和活动在内存不足的情况下被杀死,并且在NewItemActivity重新创建时,它不会重新创建MainActivity

于 2014-01-30T11:42:27.797 回答