2013-11-09 35 views
0

我試圖做一個應用程序,我可以導入圖片,添加一些細節,然後將此信息保存到設備上的SQLite數據庫。在將細節添加到數據庫之前,我將圖像壓縮並保存到設備中。當我選擇一個大的圖像,即一個來自相機並導致數據庫鎖定時,我遇到了問題?但是當保存細節時沒有成功的圖像。請看我下面的代碼和錯誤:Android位圖壓縮和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) 

回答

0

在幾種方法中(getItem,getAllItems等)您正在打開數據庫連接,然後不關閉它。確保打開後始終關閉它。

更好的是,在啓動時只打開一次,並在應用程序的整個生命週期中重複使用相同的連接。

+0

謝謝你的建議。它現在變得更加反應了,但我仍然得到這個錯誤:/ – NextGenHen

0

我有一個類似的問題。確保你插入的圖片不大。我發現我的圖片大概在6MB左右!和分貝不喜歡這個。 你想嘗試讓圖像大約0.3 MB(300 KB)。

你可以發現這一點通過調用圖像此代碼字節

someImageBytes.length 
0

堆棧跟蹤說傳遞給SQLiteOpenHelper上下文爲null。

你似乎在那裏通過MainActivity.getContext()。那是不對的。在需要數據庫的地方傳入有效的上下文。例如,在NewItemActivity可能是NewItemActivity.this或甚至getApplicationContext()

另請注意,您只能在onCreate()之前使用活動,服務或應用程序作爲上下文,而不是早期。

爲什麼發生在大圖像中是因爲應用程序和活動在低內存情況下被終止,並且當重新創建NewItemActivity時,它不會重新創建MainActivity