My situation is that: I have a button that change background of my parent layout with a image of SD (this work fine). Then I like save these image in a SharedPreference to allow the user start my app with their background image, and not my default background image. I save the image this way:
SharedPreferences.Editor editor = prefs.edit();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yourSelectedImage.compress(Bitmap.CompressFormat.JPEG, 100, baos); //bm is the bitmap object
byte[] b = baos.toByteArray();
editor.putString("background", Base64.encodeToString(b, Base64.DEFAULT ));
And I retrieve on this way (this code is in onCreate):
prefs = getSharedPreferences("Mis preferencias",Context.MODE_PRIVATE);
String fondo = prefs.getString("background", "vacio");
if(!fondo.equals("vacio")){
byte[] b = Base64.decode(fondo, Base64.DEFAULT);
InputStream is = new ByteArrayInputStream(b);
Bitmap yourSelectedImage = BitmapFactory.decodeStream(is);
BitmapDrawable bd = new BitmapDrawable(getResources(), yourSelectedImage);
View view = findViewById(R.id.padre);
view.setBackgroundDrawable(bd);
}
Is the first time that use sharedpreferences and play with images in base64, so I'm little stuck with this, if I kill my app and restart, the default backgrounds appear, instead the custom. Any help? thanks and sorry for my english.
You forgot editor.commit() to actually save you string in Preferences.
Related
how can I save an ImageView in sharedpreferences?
I am trying to create a quiz where the player needs coins to unlock the next level, so the next level will be with a lock, and as soon as the player buys the level, the lock goes away, I already got the score. save, now only the image is missing, thanks in advance everyone!
solved your problem do something like that:
Write Method to encode your bitmap into string base64-
// method for bitmap to base64
public static String encodeTobase64(Bitmap image) {
Bitmap immage = image;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
immage.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String imageEncoded = Base64.encodeToString(b, Base64.DEFAULT);
Log.d("Image Log:", imageEncoded);
ret
urn imageEncoded;
}
2.Pass your bitmap inside this method like something in your preference:
SharedPreferences.Editor editor = myPrefrence.edit();
editor.putString("namePreferance", itemNAme);
editor.putString("imagePreferance", encodeTobase64(yourbitmap));
editor.commit();
3 And when you want to display your image just anywhere, convert it into a bitmap again using the decode method:
// method for base64 to bitmap
public static Bitmap decodeBase64(String input) {
byte[] decodedByte = Base64.decode(input, 0);
return BitmapFactory
.decodeByteArray(decodedByte, 0, decodedByte.length);
}
Please pass your string inside this method and do what you want.
Get bitmap from the imageview then convert into base64 string then save it to the sharedpreference then again when you need the image get the base64 string convert to bitmap then user imageview.setBitmap(bitmap);
Now You are all set
For encoding and decoding bitmap you can use this, :
public static String encodeTobase64(Bitmap image) {
Bitmap immage = image;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
immage.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String imageEncoded = Base64.encodeToString(b, Base64.DEFAULT);
Log.d("Image Log:", imageEncoded);
return imageEncoded;
}
public static Bitmap decodeBase64(String input) {
byte[] decodedByte = Base64.decode(input, 0);
return BitmapFactory
.decodeByteArray(decodedByte, 0, decodedByte.length);
}
It isn't a good idea to store your images in shared preferences because shared preferences are used for storing app settings that are lightweight. You should use an SQLite or Room database especially if you have many images. Another way is to cache your images in external storage.
I'm successfully storing logged in user info like user name user email and other important information in shared preferences. But I'm looking for the best way to store the user's image.
You can still use sharedpreference since you store other information in shared preference too. All you have to do is, convert your image to it's Base64 string representation:
Bitmap realImage = BitmapFactory.decodeStream(stream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
realImage.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
String encodedImage = Base64.encodeToString(b, Base64.DEFAULT);
textEncode.setText(encodedImage);
SharedPreferences shre = PreferenceManager.getDefaultSharedPreferences(this);
Editor edit=shre.edit();
edit.putString("image_data",encodedImage);
edit.commit();
and then, when retrieving, convert it back into bitmap:
SharedPreferences shre = PreferenceManager.getDefaultSharedPreferences(this);
String previouslyEncodedImage = shre.getString("image_data", "");
if( !previouslyEncodedImage.equalsIgnoreCase("") ){
byte[] b = Base64.decode(previouslyEncodedImage, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
imageConvertResult.setImageBitmap(bitmap);
}
However, I have to tell you that Base64 support is only recently included in API8. To target on lower API version, you need to add it first. Luckily, this guy already have the needed tutorial.
There is a quick and dirty example on github.
Original Thread here.
Hope it helps!
This question already has answers here:
How to pass image data from one activity to another activity?
(9 answers)
Closed 5 years ago.
I have to transfer the image from one activity to another. In first activity there are two buttons (take photo) and (View Image).User can take photo by pressing (take photo) button and that photo will be transfer to another activity class which can be view by (View Image) button. Help required.
There is another way for doing this. You can convert the Bitmap image and convert into Base 64 and store it in shared preference. In another activity you can reconvert back it into bitmap and use where ever you want.
Bitmap Conversion and Storing into Shared Preference
Bitmap photo = (Bitmap) intent.getParcelableExtra("Your data");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String temp = Base64.encodeToString(b, Base64.DEFAULT);
myPrefsEdit.putString("url", temp);
myPrefsEdit.commit();
Retrieving from Shared Preference and Loading it into an ImageView
String temp = myPrefs.getString("url", "defaultString");
try {
byte[] encodeByte = Base64.decode(temp, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
picture.setImageBitmap(bitmap);
} catch (Exception e) {
e.getMessage();
}
I hava a Bitmap variable named bmp in Activity1 , and I want to send the bitmap to Activity2
Following is the code I use to pass it with the intent.
Intent in1 = new Intent(this, Activity2.class);
in1.putExtra("image",bmp);
startActivity(in1);
And in Activity2 I try to access the bitmap using the following code
Bundle ex = getIntent().getExtras();
Bitmap bmp2 = ex.getParceable("image");
ImageView result = (ImageView)findViewById(R.Id.imageView1);
result.setImageBitmap(bmp);
The application runs without an exception but it does not give the expected result
Convert it to a Byte array before you add it to the intent, send it out, and decode.
//Convert to byte array
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Intent in1 = new Intent(this, Activity2.class);
in1.putExtra("image",byteArray);
Then in Activity 2:
byte[] byteArray = getIntent().getByteArrayExtra("image");
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
edit
Thought I should update this with best practice:
In your first activity, you should save the Bitmap to disk then load it up in the next activity. Make sure to recycle your bitmap in the first activity to prime it for garbage collection:
Activity 1:
try {
//Write file
String filename = "bitmap.png";
FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE);
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
//Cleanup
stream.close();
bmp.recycle();
//Pop intent
Intent in1 = new Intent(this, Activity2.class);
in1.putExtra("image", filename);
startActivity(in1);
} catch (Exception e) {
e.printStackTrace();
}
In Activity 2, load up the bitmap:
Bitmap bmp = null;
String filename = getIntent().getStringExtra("image");
try {
FileInputStream is = this.openFileInput(filename);
bmp = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
Sometimes, the bitmap might be too large for encode&decode or pass as a byte array in the intent. This can cause either OOM or a bad UI experience.
I suggest to consider putting the bitmap into a static variable of the new activity (the one that uses it) which will carefully be null when you no longer need it (meaning in onDestroy but only if "isChangingConfigurations" returns false).
Simply we can pass only Uri of the Bitmap instead of passing Bitmap object. If Bitmap object is Big, that will cause memory issue.
FirstActivity.
intent.putExtra("uri", Uri);
From SecondActivity we get back bitmap.
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),Uri.parse(uri));
Kotlin Code for send Bitmap to another activity by intent:
1- in First Activity :
val i = Intent(this#Act1, Act2::class.java)
var bStream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 50, bStream)
val byteArray = bStream.toByteArray()
i.putExtra("image", byteArray )
startActivity(i)
2- In Activity two (Read the bitmap image) :
var bitmap : Bitmap? =null
if (intent.hasExtra("image")){
//convert to bitmap
val byteArray = intent.getByteArrayExtra("image")
bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
}
3- if you need to set it as background for a view, like ConstraintLayout or... :
if (bitmap != null) {
//Convert bitmap to BitmapDrawable
var bitmapDrawable = BitmapDrawable( resources , bitmap)
root_constraintLayout.backgroundDrawable = bitmapDrawable
}
create a singleton class for storing bitmap data
public final class BitmapData {
private static final BitmapData bitmapData = new BitmapData();
private Bitmap bitmap;
private BitmapData() {
}
public static BitmapData getInstance() {
return bitmapData;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
in first activity you can set like this.
BitmapData.getInstance().setBitmap(bitmap);
and in second activity
Bitmap bitmap = BitmapData.getInstance().getBitmap();
Note: check null value
We can also solve this without passing data through intent. Just store the image in the memory and in the next Activity just load the image from that location, which can also avoid app crash from passing large bitmap data.
Note: You need not even pass the location path to the intent, remember the path and use it.
I would like to also post a best practices answer for those looking to do this (but may be asking the wrong question).
Instead of passing a bitmap around (which I presume you downloaded from the network, otherwise, you would already have a file reference to it), I recommend using an image loader such as Universal Image Loader to download an image into an ImageView. You can configure it to then cache the image to disk:
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
.defaultDisplayImageOptions(defaultOptions)
.build();
ImageLoader.getInstance().init(config);
Now, just pass the image URL in your intent and use the UIL to load the image. In your newly created activity for example, the image will load instantly because it is loading from the cache - even if your image URL has expired since the download.
Bundle b = new Bundle();
b.putSerializable("Image", Bitmap);
mIntent.putExtras(b);
startActivity(mIntent);
I am trying to show a image saved as blob in my DB. I am using ORMLite and Android 1.6.
I created a textView who show a 'html.FromHtml'
Here is the code:
//Save the image in DB.
...
Bitmap myBitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().toString()+"/images/imagem.png");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
myBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
glossary.setImageBytes(byteArray);
'glossary' is an instance of Glossary. Who has the field 'imageBytes':
#DatabaseField(dataType = DataType.BYTE_ARRAY)
private byte[] imageBytes;
In my activity I pass this 'imageBytes' to string to use 'html.FromHtml':
//Activity
...
String htmlContent = "<h1> Title </h1>
<img src=\""+glossary.getImageBytes.toString()+"\" />"
Now in my Adapter I try to show the content of 'htmlContent':
//Adapter
...
holder.tvContent.setText(Html.fromHtml(htmlContent, new Html.ImageGetter() {
#Override
public Drawable getDrawable(String source) {
byte[] data;
data = source.getBytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//Log.i("bitmap", "bitmap height:" + String.valueOf(bitmap.getHeight) );
//THIS LOG RETURN NPE
Drawable d = null;
d = new BitmapDrawable(getResources(),bitmap);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
return d;
}
}, null));
...
I think the problem is when I change byte to string and string to byte. Because the bitmap created by 'BitmapFactory.decodeFile()' is returning a NPE.
But I don't know how fix that.
Any suggestions?
thx!
Well certainly your first problem is that you should not be doing:
glossary.getImageBytes().toString()
To turn a byte[] into a String you should do:
new String(glossary.getImageBytes())
If you do a byte[].toString() it will be set to something like:
[B#3487a5cc
Instead of a String made up of the bytes in the array.
That said, I'm not sure you can just put the bytes from a PNG file into a byte[] array to be printing out as a String. That sounds like you are going to be printing binary information in your HTML which I don't think will convert correctly. Also, it looks like you are putting the PNG bytes into the src="..." HTML section. That won't work either AFAIK.