Saving ImageView via GSON for SharedPreferences? - android

I want to save an object(of type MyObject) in Shared Preference via gson:
PS: store and retrieve a class object in shared preference
So 1 of the fields in MyObject is an ImageView which is fetched from a url.
Now when I do:
String json = gson.toJson(myObject);
I get a stackoverflow error. When I comment out the ImageView from my MyObject POJO this error gets resolved.
Q1- There are barely 8-10 images. So how do I store them through gson??
Q2- And is it a good practise to store images through gson, if not so then what better option do I have?
I think the error comes due to converting ImageView to string.

You store data that can be converted to string or numbers (long, int ...) in gson/sharedpreferences.
you can't and you shouldn't store ImageView because it is a UI object that is meant to be used to display Images in android layout.
With that being said, try saving your actual Image to a private directory that belongs to your app instead of this.
try {
Bitmap bmp = yourImageView.getDrawingCache();
FileOutputStream out = new FileOutputStream(pathToOutputFile);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
For more about storage in android : Storage Guide

Related

How to access lottie files outside res folder programatically

I don't know this is a duplicate question or not, but i tried to search similar question according to this.
I want to access the file that located outside /res folder programatically.
I already know if we want to access /res folder, then we just call it's id like getString(), getDrawable() etc.
But in my case, I want to access anim_empty.json programatically. How to do that?
Try following method for accessing JSON data:
public static String loadJSONFromAsset(Context mContext, String fileName) {
String json;
try {
InputStream is = mContext.getAssets().open(fileName);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return json;
}
Modify the method according to your usage..
In the truth, i just wanted to call the Lottie animation files, i thought that i need to write script like the answer above but all i need is just these (Getting Started With Animations in Android Using Lottie — Kotlin and enter link description here):
lottieAnimationView = findViewById(R.id.empty_hstanim);
lottieAnimationView.setAnimation("anim_empty.json");
lottieAnimationView.playAnimation();
Thanks for the kind answer anyway!

OOM on devices with smaller RAM

I have two json files in the assets folder. The problem is that on devices with smaller memory I get the out of memory error. What can I do to solve this? I have the following code:
Variables to store json
private static JSONObject one;
private static JSONObject two;
Method to set variables
public static void setJSON(Context context){
try {
one = new JSONObject(loadJSON(context,"one.json"));
two = new JSONObject(loadJSON(context,"two.json"));
} catch (JSONException e) {
e.printStackTrace();
}
}
Method to load json
private static String loadJSON(Context context, String filename){
try {
InputStream is = context.getAssets().open(filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String json = new String(buffer, "UTF-8");
return json;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
There are a couple of ideas which might help here (and it would have helped to show a JSON file snippet)
A) How big are your JSON files? JSON processing is memory heavy, as you need to have RAM for the parser and the objects it creates in memory. Can you shrink the JSONs?
B) Can you load them one at a time? process, and free?
C) If all else fails, try splitting them into bunches of several objects, then load.
D) All in all, JSON is a terrible form of serialization. If you can use Java serialization instead, you'll be looking at a LOT less memory.
Do not use JSON, but convert your data to normal SQLite database and have it prepopulated in your APK file in assets folder. Then on first run you install it to app folder (you can use this tool) and then, finally use normal database and just get data you need at that moment, without need of loading whole JSON

Why aren't all local files displaying when using ArrayList?

I'm downloading files with my app via an API (this is working perfectly). Later in my app I'm doing a call to my database to get the file info: id, name, location and return it as a HashMap:
HashMap<Integer, ArrayList<String>> imgTitle;
I take the returned HashMap, extract the ArrayList and use that to populate some buttons. the array list holds the filename and file location. When the page loads the names display correctly but the images don't always load or one loads. If I go back and reenter the activity (via a button press) I'll get different images showing up. I've sent my array to the log and the file location is present and correct for all arrays. Why are only some image showing?
for (Map.Entry<Integer, ArrayList<String>> e : imgTitle.entrySet()) {
...
ArrayList<String> catList = e.getValue();
final String catTitle = catList.get(0);
File indexImage = new File(catList.get(1));
// add images
ImageButton imgButton = new ImageButton(this);
imgButton.setImageURI(Uri.fromFile(indexImage));
...
}
The above is inside a method called on the onCreate. My assumption is maybe the setImageURI is too slow? Any ideas?
Prior to using the setImageURI I used
imgButton.setImageResource(R.drawable.test_vehicle);
as a placeholder it was working fine. However, now I have to use a file that was downloaded and saved locally.
You could try to decode a Bitmap from a stream, like this:
File indexImage = new File(catList.get(1));
InputStream imageStream = new FileInputStream(indexImage);
Bitmap backgroundImage = null;
try {
backgroundImage = BitmapFactory.decodeStream(imageStream);
}
catch(Exception e) {
e.printStackTrace();
}
finally {
try {
//Dispose of the temporary resources
imageStream.close();
imageStream = null //So that the stream is deleted on next GC
}
catch(IOException e) {
e.printStackTrace();
}
}
if (backgroundImage != null) {
ImageButton imgButton = new ImageButton(this);
imgButton.setImageBitmap(backgroundImage);
backgroundImage.recycle();
}
Note: This is pure speculation, I haven't tested any of this. It's simply the first solution that came to my mind

How can I store a non-string object in data memory?

In particular, I want to store a given gesture in the device's memory. Usually for these things I use SharedPreferences, but since gesture isn't a primitive data type, that doesn't work here; I also looked into storing it on Internal Storage, which is what I want, but the code here: http://developer.android.com/guide/topics/data/data-storage.html suggests this only works for strings.
Is there a way to easily store objects in the device memory, or do I need to convert the object to a string then back convert when I read the file?
Gesture mGesture;
SharedPreferences stored = getSharedPreferences("Shared Preferences", 0);
SharedPreferences.Editor editor = stored.edit();
byte[] storedGesture = serializeObject(mGesture);
String storedGestureString = new String(storedGesture);
editor.putString("Gesture Password", storedGestureString);
}
public static byte[] serializeObject(Object mObject){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try{
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(mObject);
out.close();
byte[] buf = bos.toByteArray();
return buf;
} catch (IOException ioe) {
Log.e("serialize object", "error", ioe);
return null;
}
}
There's the relevant code to my attempt at serializing, the app crashes when I hit the Confirm button after creating the gesture. The Confirm button runs this code, basically.
I think you can serialize the object and back. That way you'll be able to use it both with SharedPreferences and Internal Storage.
Here is a tutorial on how to implement Serialization in Java (as well as Android) -
http://www.tutorialspoint.com/java/java_serialization.htm
Look into Java's Serializable interface. You can make your own object that implements Serializable to hole the gesture, then write that object to internal storage. Here is a link for using serialization in Android.

How do you save and load mixed data types?

I have couple of dozen pieces of data that I need to save and load on start of the application. They are int, String, long , array data types. I am confused that there seems to be so many ways to do this. It seems each variation has different methods. The some of the data gets modified while the app runs. Lets say I have the following
int WifiOn="1";
private long Lasttime="00/00/00";
private String UserId="12345678";
private String URLResource[]= {"A","B","C");
//I open file...
FileOutputStream fos = openFileOutput("userPref.dat", Context.MODE_PRIVATE);
what do I do next with my four data types to save them out to internal storage?
And then what is the method to load them?
Apart from the SharedPreferences and SQLite databases that Dheeresh Singh mentions you can also use Serialization since you only use simple datatypes.
How to write data to a file with serialization:
//create an ObjectOutputStream around your (file) OutputStream
ObjectOutputStream oos = new ObjectOutputStream(fos);
//The OOS has methods like writeFloat(), writeInt() etc.
oos.writeInt(myInt);
oos.writeInt(myOtherInt);
//You can also write objects that implements Serializable:
oos.writeObject(myIntArray);
//Finally close the stream:
oos.flush();
oos.close();
How to read data from a file with serialization:
//Create an ObjectInputStream around your (file) InputStream
ObjectInputStream ois = new ObjectInputStream(fis);
//This stream has read-methods corresponding to the write-methods in the OOS, the objects are read in the order they were written:
myInt = ois.readInt();
myOtherInt = ois.readInt();
//The readObject() returns an Object, but you know it is the same type that you wrote, so just cast it and ignore any warnings:
myIntArray = (int[]) ois.readObject();
//As always, close the stream:
ois.close();
On a side note, consider wrapping your In/OutStream in a BufferedInput/OutputStream to squeeze out some extra read/write performance.
id data is limited then can use shared preference and if data is much can use SQLite database
dozen pieces of data
Better to use SQLite database which is easy and efficient also for your need
see link for how to use that
as per http://developer.android.com/guide/topics/data/data-storage.html
Your data storage options are the following:
Shared Preferences
Store private primitive data in key-value pairs.
Internal Storage
Store private data on the device memory.
External Storage
Store public data on the shared external storage.
SQLite Databases
Store structured data in a private database.
Network Connection
Store data on the web with your own network server.
if all the data is formatted the exact same way, you should probably use JSON, in a function you can create the objects and then write them into your file.
public bool writeToFile(int wifiOn, long lastTime, String userId, String [] urlResources) {
JSONObject toStore = new JSONObject();
FileOutputStream fos = openFileOutput("userPref.dat", Context.MODE_PRIVATE);
toStore.put("wifiOn", wifiOn);
toStore.put("lastTime", lastTime);
toStore.put("userId", userId);
toStore.put("urlResources", urlResources);
try {
fos.write(toStore.toString().getBytes());
fos.close();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

Categories

Resources