Better file serialization way for proper cpu usage? - android

I use following file serialization method to retrieve my data from disk.
public Vector load(String fileName) {
try {
FileInputStream fis = openFileInput(fileName);
ObjectInputStream in = new ObjectInputStream(fis);
Vector obj = (Vector) in.readObject();
in.close();
return obj;
} catch (Exception e) {
Log.e(TAG, e.toString());
}
return null;
}
I have 35K sized file to be serialized. It works perfect but thread uses cpu violently and causes slow application to use. I load this file just once.
Is there any better way for serialization or is there any different way to handle usage cpu of thread ?

You can also consider using Parcel for serialization, it's much more lightweight type of storage.
http://developer.android.com/reference/android/os/Parcelable.html

Don't use Vector, use ArrayList - there won't be any synchronization overhead.
If your operation is going long, just show a ProgressDialog within AsyncTask, like here.

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

Parsing local gpx file in Android

I followed this example to parse a local GPX file in Android:
http://android-coding.blogspot.pt/2013/01/get-latitude-and-longitude-from-gpx-file.html
All works fine to access "lat" and "long" but I need also to get the "ele" value but all my tentatives were unsuccessful.
Anyone can give me some hits to do that?
Thanks in advance!
Best regards,
NR.
I will add my library for GPX parsing to these answers: https://github.com/ticofab/android-gpx-parser. It provides two ways to parse you GPX file: once you obtain / create a GPXParser object (mParser in the examples below), you can then either parse directly your GPX file
Gpx parsedGpx = null;
try {
InputStream in = getAssets().open("test.gpx");
parsedGpx = mParser.parse(in);
} catch (IOException | XmlPullParserException e) {
e.printStackTrace();
}
if (parsedGpx == null) {
// error parsing track
} else {
// do something with the parsed track
}
or you can parse a remote file:
mParser.parse("http://myserver.com/track.gpx", new GpxFetchedAndParsed() {
#Override
public void onGpxFetchedAndParsed(Gpx gpx) {
if (gpx == null) {
// error parsing track
} else {
// do something with the parsed track
}
}
});
Contributions are welcome.
you have the "Node node = nodelist_trkpt.item(i);" in your first loop.
Get the child elements from this node an run through these child elements.
e.g.:
NodeList nList = node.getChildNodes();
for(int j=0; j<nList.getLength(); j++) {
Node el = nList.item(j);
if(el.getNodeName().equals("ele")) {
System.out.println(el.getTextContent());
}
}
Update: I've added parsing "ele" element as well, so this code could match your requirements.
I will propose different approach: https://gist.github.com/kamituel/6465125.
In my approach I don't create an ArrayList of all track points (this is done in the example you posted). Such a list can consume quite a lot of memory, which can be an issue on Android.
I've even given up on using regex parsing to avoid allocating too many objects (which causes garbage collector to run).
As a result, running Java with 16Mb heap size, parsing GPX file with over 600 points, garbage collector will be run only 12 times. I'm sure one could go lower, but I didn't optimize it heavily yet.
Usage:
GpxParser parser = new GpxParser(new FileInputStream(file));
TrkPt point = null;
while ((point = parser.nextTrkPt()) != null) {
// point.getLat()
// point.getLon()
}
I've successfully used this code to parse around 100 Mb of GPX files on Android. Sorry it's not in the regular repo, I didn't plan to share it just yet.
I've ported the library GPXParser by ghitabot to Android.
https://github.com/urizev/j4gpx

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