How to perform caching in android? - android

I am building an articles reading android application like TechChurn. I am fetching data from server in the form of json.
I am parsing Id(unique),title, author name and articles-content from json and displaying it in list-view.
Those parsed content is stored in local for accessing without internet access.
This i have done using a cache function.
Here is my code that is using for caching -
public final class CacheThis {
private CacheThis() {
}
public static void writeObject(Context context, String fileName,
Object object) throws IOException {
FileOutputStream fos;
ObjectOutputStream oos;
if (fileExistance(fileName, context)) {
fos = context.openFileOutput(fileName, Context.MODE_PRIVATE
| Context.MODE_APPEND);
oos = new AppendingObjectOutputStream(fos);
} else {
fos = context.openFileOutput(fileName, Context.MODE_PRIVATE
| Context.MODE_APPEND);
oos = new ObjectOutputStream(fos);
}
oos.writeObject(object);
oos.flush();
oos.close();
fos.close();
}
public static List<Object> readObject(Context context, String fileName) {
List<Object> list = new ArrayList<Object>(0);
FileInputStream fis;
try {
fis = context.openFileInput(fileName);
ObjectInputStream ois = new ObjectInputStream(fis);
Object object;
try {
while (true) {
object = ois.readObject();
list.add(object);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
public static boolean fileExistance(String fname, Context context) {
File file = context.getFileStreamPath(fname);
return file.exists();
}
}
my article should be cached based on id instead its been loaded for every-time when app is started

Use the following methods to store and retrieve the data.. Here you can store the object..
private void writeData(Object data, String fileName) {
try {
FileOutputStream fos = context.openFileOutput(fileName,
Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(data);
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public Object readData(String fileName){
Object data = null;
if (context != null) {
try {
FileInputStream fis = context.openFileInput(fileName);
ObjectInputStream is = new ObjectInputStream(fis);
data = is.readObject();
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return data;
}
Write the data once you got the response from the server(at first request to the server). Use the id as file name. After that check for the particular file before you want to hit server for data. If the file is available then you can get the data from that file, otherwise hit the server.

Related

Save an object or list of objects in Android

I have a list of a custom object class that I called Students, and I would like to save it in a way such that it won't be affected when we close the app completely. The class: (of course I have a constructor and stuff, but these are the fields that may be important)
public class Students implements Serializable{
private int ID;
private int imageId;
private String firstName;
private String lastName;
private Map<Date, Boolean> Attendance;
My attempt in saving and reading it (inside an activity):
public Boolean saveStudent(Students s) {//saves student into fileName (data.bin)
ObjectOutputStream oos = null;
try {
File file = new File(this.getFilesDir().toString(), fileName);
file.createNewFile();
if(!file.mkdir()){ //just to check whats the reason behind the failed attempt
Toast.makeText(this, "Security Issue", Toast.LENGTH_SHORT).show();
}
FileOutputStream fos = this.openFileOutput(fileName, this.MODE_PRIVATE);
oos = new ObjectOutputStream(fos);
oos.writeObject(s);
oos.close();
fos.close();
return true;
} catch (FileNotFoundException err) {
Toast.makeText(this, "Something went wrong while saving", Toast.LENGTH_SHORT).show();
return false;
} catch (Exception abcd) {
Toast.makeText(this, "Ooops, I don't know what's the problem. Sorry about that!", Toast.LENGTH_SHORT).show();
return false;
}
finally {//makes sure to close the ObjectOutputStream
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public Students readStudent() {//reads Student object from(data.bin) and returns it.
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("data.bin"));
ois.close();
return (Students) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
When I run, it gives me the "Something went wrong while saving" and "Security Issue". Can some one help me solve this problem?
PS: I really don't wanna use an SQLlite database because I think that it's an overkill for just 3 or 4 entries. I hope it's not one of those stupid mistakes that take several hours of staring to find out.
Please check this source. I have tested it, and it is working well.
public class LoginActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Students students = new Students();
students.setID(1234);
students.setFirstName("hello");
Log.d("test", "pre students="+students);
saveStudent(students);
Students s = readStudent();
Log.d("test", "after students="+s);
}
String fileName = "data.bin";
public Boolean saveStudent(Students s) {//saves student into fileName (data.bin)
ObjectOutputStream oos = null;
try {
/* File file = new File(this.getFilesDir().toString(), fileName);
file.createNewFile();
if(!file.mkdir()){ //just to check whats the reason behind the failed attempt
Toast.makeText(this, "Security Issue", Toast.LENGTH_SHORT).show();
}*/
FileOutputStream fos = this.openFileOutput(fileName, this.MODE_PRIVATE);
oos = new ObjectOutputStream(fos);
oos.writeObject(s);
oos.close();
fos.close();
return true;
} catch (FileNotFoundException err) {
Toast.makeText(this, "Something went wrong while saving", Toast.LENGTH_SHORT).show();
return false;
} catch (Exception abcd) {
Toast.makeText(this, "Ooops, I don't know what's the problem. Sorry about that!", Toast.LENGTH_SHORT).show();
return false;
}
finally {//makes sure to close the ObjectOutputStream
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public Students readStudent() {//reads Student object from(data.bin) and returns it.
ObjectInputStream ois = null;
Students students = new Students();
try {
/*ois = new ObjectInputStream(new FileInputStream("data.bin"));*/
ois = new ObjectInputStream(openFileInput(fileName));
students = (Students) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return students;
}
}
And for saving and loading multiple objects, please check this link How do I save and multiple objects from a single file?
No need to file.mkdir()
Give openFileOutput an absolutePath may be good.
Check here:
File file = new File(this.getFilesDir().toString(), fileName);
file.createNewFile();
//if(!file.mkdir()){ //just to check whats the reason behind the failed attempt
// Toast.makeText(this, "Security Issue", Toast.LENGTH_SHORT).show();
//}
// Use file.getAbsolutePath()
FileOutputStream fos = this.openFileOutput(file.getAbsolutePath(), this.MODE_PRIVATE);
oos =oos = new ObjectOutputStream(fos);
oos.writeObject(s);
oos.close();
fos.close();
return true;
And in the read method you should give an absolute file path
check this line : ois = new ObjectInputStream(new FileInputStream("data.bin"));
pass more information to the new FileInputStream("data.bin")
change to :new FileInputStream(new File(getContext().getFilesDir(),"data.bin"));
Do not forget the parent dir.

Read an ArrayList from Internal Storage

I have an Android application and I would like to read and write an ArrayList<MyClass> to the Internal Storage.
The writing part works (I believe, haven't tested it yet :-) ) :
ArrayList<MyClass> aList;
public void saveToInternalStorage() {
try {
FileOutputStream fos = ctx.openFileOutput(STORAGE_FILENAME, Context.MODE_PRIVATE);
fos.write(aList.toString().getBytes());
fos.close();
}
catch (Exception e) {
Log.e("InternalStorage", e.getMessage());
}
}
But what I want to do now is read the whole ArrayList from the Storage and return it as an ArrayList like so:
public ArrayList<MyClass> readFromInternalStorage() {
ArrayList<MyClass> toReturn;
FileInputStream fis;
try {
fis = ctx.openFileInput(STORAGE_FILENAME);
//read in the ArrayList
toReturn = whatever is read in...
fis.close();
} catch (FileNotFoundException e) {
Log.e("InternalStorage", e.getMessage());
} catch (IOException e) {
Log.e("InternalStorage", e.getMessage());
}
return toReturn
}
I've never read in a file with Android before, so I don't know if this is even possible.
But is there A way I can read in my custom ArrayList?
you have to serialize/deserialize your object:
Your MyClass must implments Serializable and all the member inside MyClass must be serializable
public void saveToInternalStorage() {
try {
FileOutputStream fos = ctx.openFileOutput(STORAGE_FILENAME, Context.MODE_PRIVATE);
ObjectOutputStream of = new ObjectOutputStream(fos);
of.writeObject(aList);
of.flush();
of.close();
fos.close();
}
catch (Exception e) {
Log.e("InternalStorage", e.getMessage());
}
}
to deserialize the object:
public ArrayList<MyClass> readFromInternalStorage() {
ArrayList<MyClass> toReturn;
FileInputStream fis;
try {
fis = ctx.openFileInput(STORAGE_FILENAME);
ObjectInputStream oi = new ObjectInputStream(fis);
toReturn = oi.readObject();
oi.close();
} catch (FileNotFoundException e) {
Log.e("InternalStorage", e.getMessage());
} catch (IOException e) {
Log.e("InternalStorage", e.getMessage());
}
return toReturn
}

Android:Cannot open file Not enough disk space

I have an application consist on reading AND saving an xml file and to write it if internet connection is available,else it will read the file already saved on the terminal.
WriteFeed function:
// Method to write the feed to the File
private void WriteFeed(RSSFeed data) {
FileOutputStream fOut = null;
ObjectOutputStream osw = null;
try {
fOut = openFileOutput(fileName, MODE_PRIVATE);
osw = new ObjectOutputStream(fOut);
osw.writeObject(data);
osw.flush();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
WriteFeed function:
// Method to read the feed from the File
private RSSFeed ReadFeed(String fName) {
FileInputStream fIn = null;
ObjectInputStream isr = null;
RSSFeed _feed = null;
File feedFile = getBaseContext().getFileStreamPath(fileName);
if (!feedFile.exists())
return null;
try {
fIn = openFileInput(fName);
isr = new ObjectInputStream(fIn);
_feed = (RSSFeed) isr.readObject();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
fIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return _feed;
}
I have enough diskSpace ,sometimes i get "MemoryCach will use up to 16 Mb" ,always i get "Not enough disk space,will not index" and "FeatureCode > cannot open file"
whats wrong in my app?

Store and read KeyPair with Android SharedPreferences

I'm looking for a kind of Serialization for the java.security.KeyPair to store and read from the Shared Preferences.
Storing the .toString() is now quite sinful cause there is no Constructor for the KeyPair.
Suggestions?
I'm afraid there is no way of storing a Serializable object in SharedPreferences. I recommend looking into saving it as a private file, see Android Storage Options, FileOutputStream and ObjectOutputStream for more information.
public static void write(Context context, Object obj, String filename) {
ObjectOutputStream oos = null;
try {
FileOutputStream file = context.openFileOutput(filename, Activity.MODE_PRIVATE);
oos = new ObjectOutputStream(file);
oos.writeObject(obj);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static Object read(Context context, String filename) {
ObjectInputStream ois = null;
Object obj = null;
try {
FileInputStream file = context.getApplicationContext().openFileInput(filename);
ois = new ObjectInputStream(file);
obj = ois.readObject();
} catch (FileNotFoundException e) {
// Just let it return null.
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return obj;
}
I actually solved in it this way:
I first create a String by using Base64, which I store and then recreate from the Shared Proferences:
SharedPreferences prefs = this.getSharedPreferences(
PATH, Context.MODE_PRIVATE);
String key = prefs.getString(KEYPATH, "");
if (key.equals("")) {
// generate KeyPair
KeyPair kp = Encrypter.generateKeyPair();
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o;
try {
o = new ObjectOutputStream(b);
o.writeObject(kp);
} catch (IOException e) {
e.printStackTrace();
}
byte[] res = b.toByteArray();
String encodedKey = Base64.encodeToString(res, Base64.DEFAULT);
prefs.edit().putString(KEYPATH, encodedKey).commit();
} else {
// read the KeyPair from internal storage
byte[] res = Base64.decode(key, Base64.DEFAULT);
ByteArrayInputStream bi = new ByteArrayInputStream(res);
ObjectInputStream oi;
try {
oi = new ObjectInputStream(bi);
Object obj = oi.readObject();
Encrypter.setMyKeyPair((KeyPair) obj);
Log.w(TAG, ((KeyPair) obj).toString());
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

Reading my Serialized Object from File in Android

This is my first attempt at serializing/deserializing objects on any platform and, to put it mildly, I'm confused.
After implementing Serializable to my game object I output it to a file thus:
public void saveGameState(){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(theGame);//theGame is an instance of the custom class
//TGame which stores game info.
byte[] buf = bos.toByteArray();
FileOutputStream fos = this.openFileOutput(filename,
Context.MODE_PRIVATE);
fos.write(buf);
fos.close();
} catch(IOException ioe) {
Log.e("serializeObject", "error", ioe);
}
File f =this.getDir(filename, 0);
Log.v("FILE",f.getName());
}
This seems to work, in that I get no exceptions raised. I can only know for sure when I deserialize it. Which is where things go pear shaped.
public God loadSavedGame(){
TGame g=null;
InputStream instream = null;
try {
instream = openFileInput(filename);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
try {
ObjectInputStream ois = new ObjectInputStream(instream);
try {
g= (TGame) ois.readObject();
return g;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
} catch (StreamCorruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
I got the basis of this code from here Android Java -- Deserializing a file on the Android platform and tried to modify it for my app. When running I get
05-31 23:30:45.493: ERROR/copybit(1279): copyBits failed (Invalid argument)
When the output should be loaded and the saved game start up from when it was saved.
Any help would be appreciated.
The error you've shown is not at all related to serialization: its actually a video display error. I'd suggest looking at the object BEFORE you serialize to make sure its not null, and I'd also suggest serializing to a file on the SD card to make sure you actually had data output (so use new FileOutputStream("/mnt/sdcard/serializationtest") as the output stream and new FileInputStream("/mnt/sdcard/serializationtest") as the input stream) while you are debugging; you can switch back to the context methods after it works, but make sure your sdcard is plugged in while you are doing this.
Finally, modify your logging to look like this:
try {
ObjectInputStream ois = new ObjectInputStream(instream);
try {
g= (TGame) ois.readObject();
return g;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
android.util.Log.e("DESERIALIZATION FAILED (CLASS NOT FOUND):"+e.getMessage(), e);
e.printStackTrace();
return null;
}
} catch (StreamCorruptedException e) {
android.util.Log.e("DESERIALIZATION FAILED (CORRUPT):"+e.getMessage(), e);
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (IOException e) {
android.util.Log.e("DESERIALIZATION FAILED (IO EXCEPTION):"+e.getMessage(), e);
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
and see what error gets returned. I expect the serialization is failing somehow.
To seralize or deserialize anything you can use SIMPLE api. It is very easy to use. Download the file and use it in your program
Have a look here
http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php#deserialize
Thanks Deepak
I have created below class to do the save and retrieve object.
public class SerializeUtil {
public static <T extends Serializable> void saveObjectToFile(Context context, T object, String fileName){
try {
FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(object);
os.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static<T extends Serializable> T getObjectFromFile(Context context, String fileName){
T object = null;
try {
FileInputStream fis = context.openFileInput(fileName);
ObjectInputStream is = new ObjectInputStream(fis);
object = (T) is.readObject();
is.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return object;
}
public static void removeSerializable(Context context, String filename) {
context.deleteFile(filename);
}
}

Categories

Resources