Android - What's the best way to store image to SQLite? - android

I am developing an offline application and I'm not getting any picture from user's gallery.
But I want to display the images to the users that I inserted manually.
The only solution I can think of is to put those images into drawable, then save it to the sqlite database (which I not sure how). Can this be done?
Thank you.

If you're willing to store the images in the drawable folders, you can store a reference to them in your database. Just store a string like com.example.yourapp:drawable/imagefilename and use this to display the image, where yourString contains the string from the database..
int imageResource = this.getResources().getIdentifier(yourString, null, null);
yourimageview.setImageResource(imageResource);

You can Use insert blob for this
public void insertImg(int id , Bitmap img ) {
byte[] data = getBitmapAsByteArray(img); // this is a function
insertStatement_logo.bindLong(1, id);
insertStatement_logo.bindBlob(2, data);
insertStatement_logo.executeInsert();
insertStatement_logo.clearBindings() ;
}
public static byte[] getBitmapAsByteArray(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0, outputStream);
return outputStream.toByteArray();
}

Related

android - How do I caching image and display offline?

I'm workin with Volley API in my WebServices, and then I'll write the data in with SQLITE.
Webservices that comes with a JSON with many itens, each of then has data and a image, and I need to keep this image in my cache to display offline in a ListView and later on a detail screen. In the future the user will clean these itens and clear the imagens of them too.
Well, how can I save these images in my local DB and link with each Item that I have from the JSON?
I will be, in 90% of the time, offline. I will only stay online for synchronizing and download the updated server items.
For dealing with images in Android the benchmark is to use Picasso library. It takes care of:
Handling ImageView recycling and download cancelation in an adapter;
Complex image transformations with minimal memory use;
Automatic memory and disk caching.
Besides that, if you're going to display images in lists and need animation to enhance your UI, I strongly recommend changing from ListView to RecyclerView. It is not recommended to store the images in the DB, you would lose time converting this from/to blobs (check here and here). Said that, what I suggest is:
Use Picasso to load the images from the URL provided in the JSON;
Implement a Custom target to handle the image file downloaded by Picasso;
Save the image in a folder inside your app directory;
Use RecyclerView to display the images; (optional)
If you need a project example where those things are done, you can check this. In this project I follow the approache I've described above. You can download the app from the store and see how it will download the images.
Quicky-guide:
To use Picasso add this to you module's gradle file: compile 'com.squareup.picasso:picasso:2.5.2'
Create a class that implements import com.squareup.picasso.Callback;:
public class ImageWarehouse implements Callback {
private static final String TAG = "ImageWarehouse";
private String mDirectory;
private String mFileName;
private ImageView mContainer;
#Inject
App mApplication;
public ImageWarehouse(String fileName, ImageView container, String directory) {
this.mFileName = fileName;
this.mContainer = container;
this.mDirectory = directory;
this.getStorageDir();
}
#Override
public void onSuccess() {
if (this.isExternalStorageWritable()) {
final Bitmap bitmap = ((BitmapDrawable) this.mContainer.getDrawable()).getBitmap();
new AsyncTask<Void, Void, File>() {
#Override
protected File doInBackground(Void... params) {
File file = null;
try {
file = new File(ImageWarehouse.this.getStorageDir().getPath().concat("/").concat(ImageWarehouse.this.mFileName.concat(Constants.MEDIA_EXTENSION)));
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);
ostream.close();
} catch (Exception e) {
Log.e(TAG, "External Storage is not available");
}
return file;
}
}.execute();
} else {
Log.e(TAG, "External Storage is not available");
}
}
#Override
public void onError() {
}
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
public File getStorageDir() {
File file = new File(Environment.getExternalStorageDirectory(), Constants.MEDIA_DIRECTORY.concat(this.mDirectory));
if (!file.mkdirs()) {
}
return file;
}
}
Call Picasso in order to display the image in the layout and save it to the specified path:
Picasso
.load(URL)
.fit()
.centerCrop()
.into(viewHolder.cover,
new ImageWarehouse(
name,
viewHolder.cover,
Constants.MEDIA_CHARACTER
)
);
You can user Android-Universal-Image-Loader it is also cache image in memory. it is show from cache when next time same url used in imageloader for get image
see below link for complete source code of Universal Image Loader Example.
Android - Universal Image Loader
You can save your images in Sqlite as blob and can retrieve it when required. Create table as
create table sometable(id integer primary key autoincrement,photo BLOB);
And save the image as
//convert image into byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.common)).getBitmap();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] photo = baos.toByteArray();
//And now store this image
ContentValues initialValues = new ContentValues();
initialValues.put("photo",photo);
return db.insert("sometable", null, initialValues);
And retrieve image as
Cursor cur=your query;
while(cur.moveToNext())
{
byte[] photo=cur.getBlob(index of blob cloumn);
}

Android downloading an image

Here i have stored an image by converting as string using 'base64 format' on my server,and i could able to display it in the same way on image view .But now i want download it to my sd card .I can see that some people downloading using 'URL'. But in my case there is no URL.I just converted the image into string and stored and able to display it on imageview by reconverting it.
this is the way i reconverted the string into image
//getting string from server using json parsor
String image=json_data.getString("img");
txt.setText(u);
//converting string to image
byte[] imageAsBytes = Base64.decode(p.getBytes(), 0);
im = (ImageView)this.findViewById(R.id.imageView1);
im.setImageBitmap(
BitmapFactory.decodeByteArray(imageAsBytes, 0,imageAsBytes.length));
Use Image Loader libraries instead of yours.
https://github.com/nostra13/Android-Universal-Image-Loader
https://github.com/bumptech/glide
http://square.github.io/picasso/
THIS SNIPPET SHOULD HELP !
// give any name to file xxx.jpg
File filePath = new File(Environment.getExternalStorageDirectory()+"/name.jpg");
FileOutputStream os = new FileOutputStream(filePath, true);
EDIT
Bitmap x = BitmapFactory.decodeByteArray(imageasbytes , 0 , inageasbytes.length());
x.compress(
Bitmap.CompressFormat.JPEG, 85, os);
os.flush();
os.close();
Also , add the following permission .
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
Also if you want to know how to recover it..
String imgFile = Environment.getExternalStorageDirectory() + "/name.jpg";
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile);
Imageview.setimagebitmap(mybitmap);

What data should i save in the Sqlite Database from my app?

Okay, in my app I can add custom markers with images taken from the camera intent, then that image is then displayed full screen when the user taps on the marker. Now for each marker added i had to use :
private Map<String, Bitmap> myMarkers;
then I needed to get the ID of the marker :
private String markerId;
....
markerId = marker.getId();
Then return that image to that specific marker:
Bitmap bitmap = myMarkers.get(marker.getId());
markerIcon.setImageBitmap(bitmap);
All good and working, now my question is what do i need to save to SQlite database?
Is it the myMarkers , the markerID or the bitmap or the imageData (seen in code below)?
baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 100, baos);
imageData = baos.toByteArray();
Or do I need to save all of them to the database?
Any help on this will be much appreciated!
create a column with imageData(Blob) and tag it to your markerid(Primary key). so that it is easy to get retrieve from the DB.

How to find origID for getThumbnail when taking a picture with camera.TakePicture

For getThumbnail, the android documentation has:
public static Bitmap getThumbnail (ContentResolver cr, long origId, long groupId, int kind, BitmapFactory.Options options)
I have absolutely no idea how to get origId (The ID of the original image to perform getThumbnail on) when taking a picture with Camera.TakePicture.
My current attempt, based on various other questions I've read is:
String[] projection = { MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA };
String sort = MediaStore.Images.ImageColumns._ID + " DESC";
Log.d("getting IDs:",sort);
Cursor myCursor = managedQuery(imagesUri, projection, null, null, sort);
myCursor.moveToFirst();
thumbBitmap = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(), myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns._ID)), MediaStore.Images.Thumbnails.MINI_KIND, null );
However, my log is outputting the string "_ID" for what should be the actual ID, and it then gives me a null pointer exception on the line where I try and create myCursor.
I also read as the answer to somebody else's similar question that images on the SD card don't have IDs, in which case I guess origID would actually be a URI and the docs are just messed up? I am extremely confused, and any explanation would be very very welcome.
I ended up not being able to use getThumbnail, as I could not find any working way to use the path to the location of the image succsessfully, and (at the time at least, I believe there have been reports submitted) it had issues with devices not storing their thumbnails in the expected location.
My solution to this ended up being what I had hoped I could avoid, writing my own little thumbnail generator instead of using Android's getThumbnail.
public class CreateThumbnail extends Activity {
Bitmap imageBitmap;
public Bitmap notTheBestThumbnail(String file) {
byte[] imageData = null;
try
{
final int THUMBNAIL_SIZE = 95;
FileInputStream fis = new FileInputStream(file); //file is the path to the image-to-be-thumbnailed.
imageBitmap = BitmapFactory.decodeStream(fis);
imageBitmap = Bitmap.createScaledBitmap(imageBitmap, THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 10, baos); //What image format and level of compression to use.
imageData = baos.toByteArray();
}
catch(Exception ex) {
Log.e("Something did not work", "True");
}
return imageBitmap;
}
}
I use the class like:
CreateThumbnail thumb = new CreateThumbnail();
thumb.notTheBestThumbnail(Environment.getExternalStorageDirectory() + "/exampleDir" + "/" + exampleVar + "/example_img.jpg");
Bitmap mBitmap = thumb.imageBitmap; //Assigns the thumbnail to a bitmap variable, for manipulation.
While I didn't actually figure out how to get the ID, hopefully this will help anybody facing similar problems with getThumbnail.

Android share intent on specific application and from Bitmap resource

I'm trying to share from my app to Hyves using share intent. If I have hyves app installed and share from gallery it switch to hyves app, and upload image correctly to hyves, so it should work.
Problem is, I can't find it documented how should proper intent for hyves work, but I assume that gallery uploads images only, so I have this:
Bitmap image = BitmapFactory.decodeFile(MyGlobals.INSTANCE.activeSetting.f_image_path);
It's line of code where I pull my "active" or "selected" image within my app. At this point image is saved to SD Card, so I might read uri instead of decoding file, but I want it this way to have same approach for both hyves and facebook.
Then I call:
Intent hyvesIntent = new Intent(Intent.ACTION_SEND);
hyvesIntent.setPackage("com.hyves.android.application");
hyvesIntent.setType("image/jpeg");
hyvesIntent.putExtra("image", image);
startActivityForResult(hyvesIntent, 666);
First of all, I'm not sure if setPackage is OK to be used here, but I'm checking if this package exist to enable / disable share, and this is package name that is visible.
I need Activity result to then notify that Image is shared or not.
What happens here it starts the Hyves app, but I get full white screen, and then the Hyves app times out.
So, Can I use Bitmap in intent, and is it OK to setPackage or should I setClass?
Tnx
Maybe you can not put the bitmap directly in the intent.
First convert the bitmap into a byte array than send another side and convert into bitmap
//convert bitmap to bytearray
public static byte[] getBitmapAsByteArray(Bitmap bitmap, boolean type) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (type) {
bitmap.compress(CompressFormat.PNG, 0, outputStream);
} else {
bitmap.compress(CompressFormat.JPEG, 0, outputStream);
}
return outputStream.toByteArray();
}
//convert bitmap to bytearray
public static Bitmap getBitmap(byte[] imgByte){
Bitmap bm = BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
return bm;
}
//than intent
Intent hyvesIntent = new Intent(Intent.ACTION_SEND);
hyvesIntent.setPackage("com.hyves.android.application");
hyvesIntent.setType("image/jpeg");
hyvesIntent.putExtra("image", getBitmapAsByteArray(image,true));
startActivityForResult(hyvesIntent, 666);
I hope that is right way to put image

Categories

Resources