7

I'm using the following code to delete an image. It works the first time, but when I try to capture an image and delete it I get a StaleDataException:

08-07 14:57:24.156: E/AndroidRuntime(789): java.lang.RuntimeException: Unable to               
       resume activity {com.example.cap_im/com.example.cap_im.MainActivity}:  
       android.database.StaleDataException: Attempted to access a cursor after it has been closed.

public void deleteImageFromGallery(String captureimageid) {
    Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

    getContentResolver().delete(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            BaseColumns._ID + "=?", new String[] { captureimageid });

    String[] projection = { MediaStore.Images.ImageColumns.SIZE,
            MediaStore.Images.ImageColumns.DISPLAY_NAME,
            MediaStore.Images.ImageColumns.DATA, BaseColumns._ID, };

    Log.i("InfoLog", "on activityresult Uri u " + u.toString());

    try {
        if (u != null) {
            cursor = managedQuery(u, projection, null, null, null);
        }
        if ((cursor != null) && (cursor.moveToLast())) {

            int i = getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    BaseColumns._ID + "=" + cursor.getString(3),   null);
            Log.v(TAG, "Number of column deleted : " + i);
        }
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}
Dilshi
  • 543
  • 3
  • 7
  • 17

4 Answers4

43

Function, managedQuery() is deprecated.

Please use getContentResolver().query().

The parameters is the same.

chancyWu
  • 14,073
  • 11
  • 62
  • 81
Tom Lin
  • 491
  • 4
  • 9
8

In your finally block, you close the cursor, but you do not set it to null. Thus, the next time your method is called, cursor.getString(3) fails, since the cursor has been closed.

Workaround: Set cursor to null in your finally block.

Correct solution: Don't use an instance variable for your cursor, use a local variable in your method instead.

Heinzi
  • 167,459
  • 57
  • 363
  • 519
2

I had a similar problem. In my case the code is fine but I used the deprecated method 'managedQuery' rather than the one suggested by Tom Lin

public String getPath(Uri uri) {
    if (uri == null) {
        return null;
    }
    String result = null;

    String[] projection = {MediaStore.Images.Media.DATA};
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);

    // deprecated:
    // Cursor cursor = managedQuery(uri, projection, null, null, null);

    if (cursor != null) {

        int columnIndex = 0;
        try {
            columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            result = cursor.getString(columnIndex);
        } catch (IllegalArgumentException e) {
            Log.e("While getting path for file", e);
        } finally {
            try {
                if (!cursor.isClosed()) {
                    cursor.close();
                }
                cursor = null;
            } catch (Exception e) {
                Log.e("While closing cursor", e);
            }
        }
    }
    return result;
}

If I use the deprecated method it still works if I omit the finally. It is also explicitly stated in the doc that one should not close the cursor when using this method

JoachimR
  • 5,150
  • 7
  • 45
  • 50
0

Also don't use managedQuery() it has been deprecated.

Remove this:

protected SQLiteDatabase database;

and make it local

Basically 2 method are executing concurrently and one method called database.close() and 2nd method is still accessing data so the Exception

use this:

   public class db {

    DataBaseHelper dbHelper;
    Context mContext;


    public db(Context context) {
        this.mContext = context;
    }

    public db open() throws SQLException {
        dbHelper = new DataBaseHelper(mContext);
        return this;
    }


    public void close() {
        dbHelper.close();
    }

    public void insertdb( int id,String ph_num, String call_type, String calldate, String call_duration, String upload_status) {
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DataBaseHelper.id,id);
        values.put(DataBaseHelper.phone_number, ph_num);
        values.put(DataBaseHelper.call_type, call_type);
        values.put(DataBaseHelper.call_date, calldate);
        values.put(DataBaseHelper.call_duration, call_duration);
        values.put(DataBaseHelper.upload_status, upload_status);
        database.insert(DataBaseHelper.table_name, null, values);
        database.close();
        // Log.d("Database helper", "values inserted");
    }


    public ArrayList<HashMap<String, String>> getAllUsers() {
        ArrayList<HashMap<String, String>> wordList;
        wordList = new ArrayList<HashMap<String, String>>();
        String selectQuery = "SELECT  * FROM call_logtable";
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        Cursor cursor = database.rawQuery(selectQuery, null);
        if (cursor.moveToFirst()) {
            do {
                HashMap<String, String> map = new HashMap<String, String>();
                map.put("id", cursor.getString(0));
                map.put("phone_number", cursor.getString(1));
                map.put("call_type", cursor.getString(2));
                map.put("call_date", cursor.getString(3));
                map.put("call_duration", cursor.getString(4));
                wordList.add(map);
            } while (cursor.moveToNext());
        }
        cursor.close(); // just added
        database.close();
        return wordList;
    }

    /**
     * Compose JSON out of SQLite records
     * @return
     */
    public String composeJSONfromSQLite(){
        ArrayList<HashMap<String, String>> wordList;
        wordList = new ArrayList<HashMap<String, String>>();
        String selectQuery = "SELECT  * FROM call_logtable where upload_status = '"+"no"+"'";
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        Cursor cursor = database.rawQuery(selectQuery, null);
        if (cursor.moveToFirst()) {
            do {
                HashMap<String, String> map = new HashMap<String, String>();
                map.put("id", cursor.getString(0));
                map.put("phone_number", cursor.getString(1));
                map.put("call_type", cursor.getString(2));
                map.put("call_date", cursor.getString(3));
                map.put("call_duration", cursor.getString(4));
                wordList.add(map);
            } while (cursor.moveToNext());
        }
        cursor.close(); // just added
        database.close();
        Gson gson = new GsonBuilder().create();
        //Use GSON to serialize Array List to JSON
        return gson.toJson(wordList);
    }


    public int dbSyncCount(){
        int count = 0;
        String selectQuery = "SELECT  * FROM call_logtable where upload_status = '"+"no"+"'";
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        Cursor cursor = database.rawQuery(selectQuery, null);
        count = cursor.getCount();
        cursor.close(); // just added
        database.close();
        return count;
    }


    public void updateSyncStatus(String id, String status){
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        String updateQuery = "Update call_logtable set upload_status = '"+ status +"' where id="+"'"+ id +"'";
        Log.d("query", updateQuery);
        database.execSQL(updateQuery);
        database.close();
    }

    public Cursor getinformation()
    {
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        String[] columns={DataBaseHelper.phone_number,DataBaseHelper.call_type,DataBaseHelper.call_date,DataBaseHelper.call_duration,DataBaseHelper.upload_status};
        return database.query(DataBaseHelper.table_name,columns,null,null,null,null,null);
    }

    public void delete()
    {
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        // String[] columns={DataBaseHelper.phone_number,DataBaseHelper.call_type,DataBaseHelper.call_date,DataBaseHelper.call_duration};
        database.delete(DataBaseHelper.table_name, null, null);
    }


    StringBuffer readSpecificfrom_db(String type)
    {
        String ph_number=null;
        String call_type=null;
        String call_date=null;
        String call_duration=null;
        String upload_status=null;
        StringBuffer sb = new StringBuffer();
        //sb.append("Call Log :");
        Cursor cursor_object=getinformation();
        cursor_object.moveToFirst();
        do {
            if((cursor_object.getString(1)).equals(type)) {
                ph_number = cursor_object.getString(0);
                call_type = cursor_object.getString(1);
                call_date = cursor_object.getString(2);
                call_duration = cursor_object.getString(3);
                if(type=="Missed") {
                    sb.append("\nPhone Number:--- " + ph_number +
                                    " \nCall Type:--- " + call_type +
                                    " \nCall Date:--- " + call_date
                            //   + " \nCall duration in sec :--- " + call_duration
                    );
                    sb.append("\n----------------------------------");
                }
                else
                {
                    sb.append("\nPhone Number:--- " + ph_number +
                            " \nCall Type:--- " + call_type +
                            " \nCall Date:--- " + call_date
                            + " \nCall duration in sec :--- " + call_duration);
                    sb.append("\n----------------------------------");
                }
            }
        }while(cursor_object.moveToNext());
        cursor_object.close(); // just added
        return sb;

    }

    StringBuffer readfrom_db()
    {
        String ph_number=null;
        String call_type=null;
        String call_date=null;
        String call_duration=null;
        String upload_status;
        //  int id=0;
        StringBuffer sb = new StringBuffer();
        // sb.append("Call Log :");
        Cursor cursor_object=getinformation();
        cursor_object.moveToFirst();
        do {
            ph_number=cursor_object.getString(0);
            call_type=cursor_object.getString(1);
            call_date=cursor_object.getString(2);
            call_duration=cursor_object.getString(3);
            sb.append("\nPhone Number:--- " + ph_number +
                    " \nCall Type:--- " + call_type +
                    " \nCall Date:--- " + call_date
                    + " \nCall duration in sec :--- " + call_duration);
            sb.append("\n----------------------------------");

        } while(cursor_object.moveToNext());
        cursor_object.close(); // just added
        return sb;
    }
}
JAAD
  • 12,349
  • 7
  • 36
  • 57