Hello im trying to save a image location on sreen to internal storage but I get a NotSerializableException.I went searching and found that the problem is that Bitmap is not designed to be serialized at this link Problem serializing Drawable I never really understood how he fix the problem throw the example. if someone could explain how he fix his NotSerializableException and help me get with mine it would be greatly appreciated
Here is my Elememt Class
public class Element extends main implements Serializable{
private int mX;
private int mY;
int location2 ;
Matrix elementlocation;
private Bitmap mBitmap;
Canvas canvas2;
public Element(Resources res, int x, int y) {
location2 =item3;
mBitmap = BitmapFactory.decodeResource(res, location2);
mX = x - mBitmap.getWidth() / 2;
mY = y - mBitmap.getHeight() / 2;
}
public Element(){
}
public void doDraw2(Canvas canvas) {
elementlocation=new Matrix();
elementlocation.postTranslate(mX,mY);
canvas2=canvas;
canvas2.drawBitmap(mBitmap, elementlocation,null);
}
public void setelementlocation(float num1,float num2){
elementlocation=new Matrix();
elementlocation.postTranslate(num1,num2);
}
public Canvas getCanvas2(){
return(canvas2);
}
public String toString() {
String sentence;
sentence= mBitmap+" "+mX+" "+mY;
return (sentence);
}
}
Here is my onTouch method in my Panel class
public boolean onTouchEvent(MotionEvent event) {
mainactivity=new main();
Log.v("test", "you have touched the sreen: ");
mElements.add(new Element(getResources(),(int) event.getX(),(int) event.get()));
mainactivity.writeElement(new Element(getResources(),(int) event.getX(),(int) event.getY()),this.getContext());
Log.v("Gesture", "is 1 ");
return super.onTouchEvent(event);
}
Here is my write element method in my main class
public void writeElement(Element obj, Context context){
Log.v("main", "made it to method writeElement" );
File f = new File(context.getFilesDir(),FILENAME);
try {
fos = new FileOutputStream(f);
ObjectOutputStream objectwrite = new ObjectOutputStream(fos);
objectwrite.writeObject(obj);
fos.close();
Log.v("main", "file was made File ");
}catch (FileNotFoundException e){
e.printStackTrace();
Log.v("main", "file was not made File not found ");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.v("main", "file was not made File IOException ");
}
}
Update
public Element(Resources res, int x, int y) {
location2 =item3;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
mBitmap = BitmapFactory.decodeResource(res, location2);
mX = x - mBitmap.getWidth() / 2;
mY = y - mBitmap.getHeight() / 2;
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
}
I just ran into the same problem. As Peter pointed out, several Classes that you use are not Serializable.
The default mechanism of Java will try to serialize your class that you marked as Serializable and try to persist all fields not marked as transient
.
If one of these fields however is not Serializable (such as android.graphics.Bitmap), then the call to ObjectOutputStream.writeObject will fail.
To work around this, you will need to override how Java serializes your Element class. For my CachedBitmap class, I used the following code.
package XXX;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
import org.apache.commons.io.output.ByteArrayOutputStream;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class CachedBitmap implements Serializable{
private static final long serialVersionUID = -6298516694275121291L;
Date inserted;
transient Bitmap bitmap;
String url;
public CachedBitmap(){};
public CachedBitmap(Bitmap b, Date insertionDate, String sourceUrl){
bitmap = b;
inserted = insertionDate;
url = sourceUrl;
}
private void writeObject(ObjectOutputStream oos) throws IOException{
// This will serialize all fields that you did not mark with 'transient'
// (Java's default behaviour)
oos.defaultWriteObject();
// Now, manually serialize all transient fields that you want to be serialized
if(bitmap!=null){
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
boolean success = bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
if(success){
oos.writeObject(byteStream.toByteArray());
}
}
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
// Now, all again, deserializing - in the SAME ORDER!
// All non-transient fields
ois.defaultReadObject();
// All other fields that you serialized
byte[] image = (byte[]) ois.readObject();
if(image != null && image.length > 0){
bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
}
}
}
For Canvas
and Matrix
you will need to find suitable (serializable) representations to store them in. For example, you could use the Matrix.getValues()
and Matrix.setValues(...)
method to translate it into a serializable format.
Hope this helps you. You might also to want to consult the following reference material by Oracle concerning Serialization: Basics and Advanced
Your problem is not only Bitmap
, but also Canvas
and Matrix
. Neither of those classes is Serializable
.
You dont need to serialize the whole Element
object, but only relevant data, like parameters of Matrix
and of course the Bitmap
.
For serializing Bitmap:
bmp.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
and Matrix
// get matrix values
float[] matrixValues = new float[9];
matrix.getValues(matrixValues);
// float[] to byte[]
ByteBuffer byteBuf = ByteBuffer.allocate(4 * array.length);
FloatBuffer floatBuf = byteBuf.asFloatBuffer();
floatBuf.put(array);
byte [] byte_array = byteBuf.array();
// write data
outputStream.write(byte_array);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With