0

So, I have a method that downloads image from url and transfer it to byte[]. Then, I put that byte[] into my database. I used blob type for my column, but it is giving me an error. Here is the method that downloads the image from url:

public static byte[] getByteFromUrl(URL src) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    InputStream is = null;
    try {
        is = src.openStream();
        byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
        int n;

        while ((n = is.read(byteChunk)) > 0) {
            baos.write(byteChunk, 0, n);
        }
        return baos.toByteArray();
    } catch (IOException e) {
        System.err.printf("Failed while reading bytes from %s: %s", src.toExternalForm(), e.getMessage());
        e.printStackTrace();
        // Perform any other exception handling that's appropriate.
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return null;
}

and the method for inserting to database:

/**
 * Method for adding UserData into local database
 *
 * @param userData object that has all the user data information
 * @param id       id of the user
 */
public void addUserData(UserData userData, long id, byte[] picture) {
    SQLiteDatabase db = getWritableDatabase();
    ContentValues values = new ContentValues();

    values.put(USER_DATA_ID, id);
    values.put(USER_DATA_FIRST_NAME, userData.getFistName());
    values.put(USER_DATA_LAST_NAME, userData.getLastName());
    values.put(USER_DATA_NICK_NAME, userData.getNickname());
    values.put(USER_DATA_DISPLAY_NAME, userData.getHowPeopleSeeMe());
    values.put(USER_DATA_EMAIL, userData.getEmail());
    values.put(USER_DATA_PHONE_NUMBER, userData.getMobilePhoneNumber());
    values.put(USER_DATA_GENDER, userData.getGender());
    values.put(USER_DATA_RATING, userData.getReliabilityRating());
    values.put(USER_DATA_PASSWORD, userData.getPassword());
    values.put(USER_DATA_PICTURE, picture);

    db.insert(TABLE_USER_DATA, null, values);
}

Now, everything goes smoothly, until I want to get everything from the database:

/**
 * Method that fetches user data from local database
 *
 * @return UserData object is returned
 */
public UserData getUserData() {
    UserData userData = new UserData();
    SQLiteDatabase db = getReadableDatabase();
    String selectQuery = "SELECT * FROM " + TABLE_USER_DATA;
    Cursor c = db.rawQuery(selectQuery, null);
    if (c.moveToFirst()) {
        do {
            long id = c.getLong(0);
            userData.setFistName(c.getString(1));
            userData.setLastName(c.getString(2));
            userData.setNickname(c.getString(3));
            userData.setHowPeopleSeeMe(c.getString(4));
            userData.setEmail(c.getString(5));
            userData.setMobilePhoneNumber(c.getString(6));
            userData.setGender(c.getInt(7));
            userData.setPicture(c.getBlob(8) != null ? getImage(c.getBlob(8)) : null);
            userData.setReliabilityRating(c.getInt(9));
            userData.setPassword(c.getString(10));
            return userData;
        } while (c.moveToNext());

    }
    c.close();
    return null;
}

where getImage method is:

 /**
 * Method for converting bytes to bitmap
 *
 * @param image bytes[] that we are converting to bitmap
 * @return bitmap image
 */
public Bitmap getImage(byte[] image) {
    return BitmapFactory.decodeByteArray(image, 0, image.length);
}

The error I'm getting is next:

    12-28 13:41:32.348 8057-8057/share.advice.khalifa.adviceshare E/CursorWindow: Failed to read row 0, column 0 from a CursorWindow which has 0 rows, 11 columns.
12-28 13:41:32.349 8057-8057/share.advice.khalifa.adviceshare D/AndroidRuntime: Shutting down VM
12-28 13:41:32.349 8057-8057/share.advice.khalifa.adviceshare E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                Process: share.advice.khalifa.adviceshare, PID: 8057
                                                                                java.lang.RuntimeException: Unable to start activity ComponentInfo{share.advice.khalifa.adviceshare/share.advice.khalifa.adviceshare.ui.activities.MainActivity}: java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
                                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
                                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                                                                                    at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                    at android.os.Looper.loop(Looper.java:148)
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                    at java.lang.reflect.Method.invoke(Native Method)
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                                                 Caused by: java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
                                                                                    at android.database.CursorWindow.nativeGetLong(Native Method)
                                                                                    at android.database.CursorWindow.getLong(CursorWindow.java:511)
                                                                                    at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
                                                                                    at share.advice.khalifa.adviceshare.io.SQLDatabase.getUserData(SQLDatabase.java:178)
                                                                                    at share.advice.khalifa.adviceshare.io.model.Model.setUpModel(Model.java:179)
                                                                                    at share.advice.khalifa.adviceshare.ui.activities.MainActivity.onCreate(MainActivity.java:115)
                                                                                    at android.app.Activity.performCreate(Activity.java:6251)
                                                                                    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                                                                                    at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                    at android.os.Looper.loop(Looper.java:148) 
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                                                    at java.lang.reflect.Method.invoke(Native Method) 
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
7
  • read row 0, column 0 from a CursorWindow which has 0 rows, 11 columns it mean ur database is empty table created but no value for that Commented Dec 28, 2015 at 13:09
  • @DarshanKachhadiya know what it means, how to prevent it from happening? Commented Dec 28, 2015 at 13:10
  • 1
    Looking at the stack trace android.database.CursorWindow.getLong(CursorWindow.java:511) It pretty much seems the reason. Commented Dec 28, 2015 at 13:18
  • 1
    You should not put images in SQLite DB because Cursor windows cannot be more than 1mb in size. Refer to this answer: stackoverflow.com/a/5981771/906362 Commented Dec 28, 2015 at 13:49
  • 1
    better create directory in sdcard and save and access images by its name. it is not good practice to save images in sqlite. Commented Dec 28, 2015 at 13:50

3 Answers 3

1

I'm not an Android expert, however I'm a little worried by c.getLong(0);.

Failed to read row 0, column 0 from a CursorWindow which has 0 rows, 11 columns 

Is your cursor returning 0 rows ?

Sign up to request clarification or add additional context in comments.

5 Comments

yes, It look like it is not accepting the byte[], cause when I do it without the picture, everything is working fine.
in Android u put blob datatype as image
If the cursor is returning zero rows, then moveToFirst() would return false, according to the docs, so I think this is not the problem.
@JonasCz thats what I was thinking. So, any solution?
@MiljanVulovic, in your method where you are inserting the data to database, I don't see the image data being actually put into the database.. Maybe that is the problem ?
1

In your updateUserData method where you are inserting the data into the database, I don't see the image data being actually added to the database.. Maybe that is the problem ?

Comments

0

Ok, so, you want to do it like this:

On your on create check if the directory you want to put your pictures exists:

private boolean createDir() {
        File myDir = new File(getCacheDir(), "profile_picture");
        Log.d("CreateDir", myDir.mkdir() ? "Yes" : "No");
        return myDir.mkdir();
    }

Now, you want to download Image from URL in byte[]:

 // DownloadImage AsyncTask
    private class DownloadImage extends AsyncTask<String, Void, byte[]> {

        UserData userData;

        public DownloadImage(UserData userData) {
            this.userData = userData;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected byte[] doInBackground(String... URL) {
            try {
                return ViewUtils.getByteFromUrl(new URL(URL[0]));
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(byte[] result) {
            File photo = new File(getCacheDir() + "/profile_picture/", "photo.jpg");
            if (photo.exists()) {
                photo.delete();
            }
            try {
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(photo));
                bos.write(result);
                bos.flush();
                bos.close();
            } catch (java.io.IOException e) {
                Log.e("PictureDemo", "Exception in photoCallback", e);
            }

        }

    }

where

ViewUtils.getByteFromUrl(new URL(URL[0]));

is

public static byte[] getByteFromUrl(URL src) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        InputStream is = null;
        try {
            is = src.openStream();
            byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
            int n;

            while ((n = is.read(byteChunk)) > 0) {
                baos.write(byteChunk, 0, n);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            System.err.printf("Failed while reading bytes from %s: %s", src.toExternalForm(), e.getMessage());
            e.printStackTrace();
            // Perform any other exception handling that's appropriate.
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

And now you have succesfully saved your image to local storage.

2 Comments

So, dont store image as blob?
@MiljanVulovic No, cursor has limit, so its better to store your image in your local and as byte[].

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.