17

I am developing a painting app in which i want to pass a Bitmap image from one activity to another but the project is not responding. I converted the relative layout screenshot into a bitmap and passing it through Intent but the problem is not solved. Here is my code....

DrawingActivity

package com.newdrawing;
public class DrawingActivity extends Activity {
    private Bitmap  mBitmap;
    private Canvas  mCanvas;
    private Path    mPath;
    private Paint   mBitmapPaint;
    private Paint   mPaint;
    MyDrawView myDrawView;
    RelativeLayout parent;
    Bitmap bitmap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawing);

        parent = (RelativeLayout) findViewById(R.id.singleparent);
        myDrawView = new MyDrawView(this);
        parent.addView(myDrawView);
        Activity context;
        //RelativeLayout item = (RelativeLayout)findViewById(R.id.item);
        View child = getLayoutInflater().inflate(R.layout.trans, null);
        parent.addView(child);   
   }

   public void color(View v) {
       switch (v.getId()) {
        case R.id.button3:
           parent.setBackgroundColor(Color.RED);
            break;
        case R.id.button4:
             parent.setBackgroundColor(Color.GREEN);
            break;
        case R.id.button5:
             parent.setBackgroundColor(Color.BLUE);
            break;
        }
    }
    public void save(View v) {
     parent.setDrawingCacheEnabled(true);
     bitmap=parent.getDrawingCache();
     parent.setDrawingCacheEnabled(false);
       Log.e("Bitmap",String.valueOf(bitmap));

    // send();

    //Canvas c = new Canvas(bitmap);
    //.draw(c);
    // File outputFile; // Where to save it
     //FileOutputStream out = new FileOutputStream(imageFile);
    // boolean success = bitmap.compress(CompressFormat.PNG, 100, out);
    // out.close();

    Intent i = new Intent(this, ImageActivity.class);
       ByteArrayOutputStream bs = new ByteArrayOutputStream();
     bitmap.compress(Bitmap.CompressFormat.PNG, 50, bs);
     byte[] byteArray = bs.toByteArray();
     i.putExtra("byteArray", byteArray);
     startActivity(i);
 }

 private void send()
 {
    Intent i9=new Intent(DrawingActivity.this,ImageActivity.class);
    i9.putExtra("Image",bitmap);
    startActivity(i9);
 }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_drawing, menu);
        return true;
    }
    public class MyDrawView extends View {

        public MyDrawView(Context c) {
            super(c);

            mPath = new Path();
            mBitmapPaint = new Paint(Paint.DITHER_FLAG);

            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setDither(true);
            mPaint.setColor(0xFF000000);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeJoin(Paint.Join.ROUND);
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            mPaint.setStrokeWidth(3);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
            canvas.drawColor(Color.TRANSPARENT);

            canvas.drawPath(mPath, mPaint);
        }

        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;

        private void touch_start(float x, float y) {
            mPath.reset();
            mPath.moveTo(x, y);
            mX = x;
            mY = y;
        }
        private void touch_move(float x, float y) {
            float dx = Math.abs(x - mX);
            float dy = Math.abs(y - mY);
            if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
                mX = x;
                mY = y;
            }
        }
        private void touch_up() {
            mPath.lineTo(mX, mY);
            // commit the path to our offscreen
            mCanvas.drawPath(mPath, mPaint);
            // kill this so we don't double draw
            mPath.reset();
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touch_start(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE:
                    touch_move(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    touch_up();
                    invalidate();
                    break;
            }
            return true;
        }

        public void clear(){
            mBitmap.eraseColor(Color.TRANSPARENT);
            invalidate();
            System.gc();
        }
    }
}

ImageActivity

package com.newdrawing;
public class ImageActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image);
        Intent i =  getIntent();

        ImageView img=(ImageView)findViewById(R.id.image11);
     /*
       if(getIntent().hasExtra("byteArray")) 
       {

           Bitmap b = BitmapFactory.decodeByteArray(
                getIntent().getByteArrayExtra("byteArray"),0,getIntent().getByteArrayExtra("byteArray").length);        
          img.setImageBitmap(b);
           Log.e("Bitmap",String.valueOf(b));

       }*/

       Bundle extras = getIntent().getExtras();
       byte[] byteArray = extras.getByteArray("byteArray");

       Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
       img.setImageBitmap(bmp);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_image, menu);
        return true;
    }
 }

Locat Report

10-16 10:39:22.653: E/AndroidRuntime(339): FATAL EXCEPTION: main
10-16 10:39:22.653: E/AndroidRuntime(339): java.lang.IllegalStateException: Could not execute method of the activity
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.view.View$1.onClick(View.java:2072)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.view.View.performClick(View.java:2408)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.view.View$PerformClick.run(View.java:8816)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.os.Handler.handleCallback(Handler.java:587)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.os.Handler.dispatchMessage(Handler.java:92)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.os.Looper.loop(Looper.java:123)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.app.ActivityThread.main(ActivityThread.java:4627)
10-16 10:39:22.653: E/AndroidRuntime(339):  at java.lang.reflect.Method.invokeNative(Native Method)
10-16 10:39:22.653: E/AndroidRuntime(339):  at java.lang.reflect.Method.invoke(Method.java:521)
10-16 10:39:22.653: E/AndroidRuntime(339):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
10-16 10:39:22.653: E/AndroidRuntime(339):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
10-16 10:39:22.653: E/AndroidRuntime(339):  at dalvik.system.NativeStart.main(Native Method)
10-16 10:39:22.653: E/AndroidRuntime(339): Caused by: java.lang.reflect.InvocationTargetException
10-16 10:39:22.653: E/AndroidRuntime(339):  at com.newdrawing.DrawingActivity.save(DrawingActivity.java:91)
10-16 10:39:22.653: E/AndroidRuntime(339):  at java.lang.reflect.Method.invokeNative(Native Method)
10-16 10:39:22.653: E/AndroidRuntime(339):  at java.lang.reflect.Method.invoke(Method.java:521)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.view.View$1.onClick(View.java:2067)
10-16 10:39:22.653: E/AndroidRuntime(339):  ... 11 more
10-16 10:39:22.653: E/AndroidRuntime(339): Caused by: java.lang.IllegalStateException: Can't compress a recycled bitmap
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.graphics.Bitmap.checkRecycled(Bitmap.java:180)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.graphics.Bitmap.compress(Bitmap.java:572)
10-16 10:39:22.653: E/AndroidRuntime(339):  ... 15 more
Joseph Quinsey
  • 8,830
  • 10
  • 49
  • 71
Deepu
  • 313
  • 1
  • 4
  • 15

8 Answers8

55

You can simply try with below -

Intent i = new Intent(this, Second.class)
i.putExtra("Image", bitmap);
startActivity(i)

And, in Second.class

Bitmap bitmap = (Bitmap) intent.getParcelableExtra("Image");

Have a look at here If you want to compress your Bitmap before sending to next activity just have a look at below -

Intent i = new Intent(this, NextActivity.class);
Bitmap b; // your bitmap
ByteArrayOutputStream bs = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 50, bs);
i.putExtra("byteArray", bs.toByteArray());
startActivity(i);

in your nextactivity -

if(getIntent().hasExtra("byteArray")) {
    ImageView previewThumbnail = new ImageView(this);
    Bitmap b = BitmapFactory.decodeByteArray(
                    getIntent().getByteArrayExtra("byteArray"),0,getIntent()
                    .getByteArrayExtra("byteArray").length);        
    previewThumbnail.setImageBitmap(b);
}
Community
  • 1
  • 1
Praveenkumar
  • 25,322
  • 23
  • 89
  • 166
  • I want to erase the bitmap using the Mode.CLEAR . I want to change the default color (black) in to developer defined color . Can u help me?? @Spk – Deepu Oct 16 '12 at 10:56
  • 1
    Thank u . If u get any idea . Tell me how to do it – Deepu Oct 16 '12 at 12:48
3

There are lots of ways :

1)

Bitmap implements Parcelable, so you could always pass it in the intent:

Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);

and retrieve it on the other end:

Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");

2)

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);
Rahil Ali
  • 861
  • 10
  • 22
2

I have answered a similar question in this SO post. My solution will save the image in the internal storage of the device inaccessible by other apps(on unrooted phones). Then we can simply decode the file and show it in imageview. It prevents TranscationTooLarge exception as you cannot exceed 1mb limit of passing bundle.

Community
  • 1
  • 1
Illegal Argument
  • 9,249
  • 2
  • 38
  • 56
2

I think that for most cases, it's ok to put the bitmap on a static reference that should be null-ed when the receiving activity doesn't need it anymore.

This way, it's very fast and doesn't need to be converted or encoded&decoded. It also doesn't leave traces behind.

android developer
  • 106,412
  • 122
  • 641
  • 1,128
1

If your Images are static and in drawable folder etc So send the bitmap from intent to next activity very costly( For Machine :) ) So Now is the best approach is to firstly create string-array in strings.xml like here.

<resources>
    <string name="app_name">Gallery App</string>
    <string-array name="images">
        <item>@drawable/img1</item>
        <item>@drawable/img2</item>
        <item>@drawable/img3</item>
        <item>@drawable/img4</item>
        <item>@drawable/img5</item>
        <item>@drawable/img6</item>
    </string-array>
</resources>

Then in your activity to get List of images related to imagesthat array declared in above.

1:-Declare the instance of TypeArray typeArray

2:-Assign typeArray = getResources().obtainTypedArray(R.array.images);

3:-Declare your List and add each item one by one ->

     ArrayList list = new ArrayList();
    for (int i = 0 ;i< typedArray.length() ; i++){

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),typedArray.getResourceId(i ,-1));
            list.add(bitmap);

        }

4:-Of course now you will set this list in your ArrayAdapter

view.setAdapter(new ArrayAdapter(this , R.layout.viewImages , list));

5:-Send cliked bitmapimage to your next Activity

 view.setOnItemClickedListener(new AdapterView.OnItemClickedListener(){


            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                    Intent i = new Intent(MainActivity.this , DetailedImageActivity.class);
                    int imageId = typedArray.getResourceId(position , -1);
                    i.putExtra("imageId",imageId) ;
                    Log.i("ResourceId ","here");
                    startActivity(i);


            }

    });

6:-Recieve your bitmap Id and get Your bitmap Image

public class DetailedImageActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detailed_image);

        ImageView imageView = (ImageView) findViewById(R.id.detailImageView);

        String title = getIntent().getStringExtra("title");
        int imageId = getIntent().getExtras().getInt("imageId") ;

        Bitmap image = BitmapFactory.decodeResource(getResources() ,imageId);
            imageView.setImageBitmap(image);


    }
}
0

You can use bundle to pass bitmap from one activity to another

Add your image into Byte array :

ArrayList<byte[]> image=new ArrayList<byte[]>();

Bundle b = new Bundle();
Intent it=new Intent(getBaseContext(),your.class);
b.putByteArray("image", image.get(position));
it.putExtras(b);
startActivity(it);

And get your image in on create of receiver activity from bundle

Mohammed Azharuddin Shaikh
  • 39,642
  • 13
  • 90
  • 114
J.D.
  • 1,364
  • 1
  • 11
  • 20
0

In your logcat it states

10-16 10:39:22.653: E/AndroidRuntime(339): Caused by: java.lang.IllegalStateException: Can't compress a recycled bitmap
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.graphics.Bitmap.checkRecycled(Bitmap.java:180)
10-16 10:39:22.653: E/AndroidRuntime(339):  at android.graphics.Bitmap.compress(Bitmap.java:572)

Your bitmap was recycled before it was passed to the ImageActivity. You could make the bitmap static so it wouldn't be recycled.

Yicanis
  • 308
  • 1
  • 16
-1

I am searching for it so much and finally find answer in https://eazyprogramming.blogspot.com/2013/01/passing-image-between-activities.html#comment-form

in First Activity

Intent intent=new Intent(FirstClass.this, SecondClass.class);
Bundle bundle=new Bundle();
bundle.putInt("image",R.drawable.ic_launcher);
intent.putExtras(bundle);
startActivity(intent);

in Second Acticity:

Bundle bundle=this.getIntent().getExtras();
int pic=bundle.getInt("image");
v.setImageResource(pic);

another method: in First Activity:

Bundle extras = getIntent().getExtras();
byte[] b = extras.getByteArray("picture");
Bitmap bmp = BitmapFactory.decodeByteArray(b, 0, b.length);
ImageView image = (ImageView) findViewById(R.id.imageView1);
image.setImageBitmap(bmp); 

in Second Acticity:

Bundle extras = getIntent().getExtras();byte[] b = extras.getByteArray("picture");Bitmap bmp = BitmapFactory.decodeByteArray(b, 0, b.length);ImageView image = (ImageView) findViewById(R.id.imageView1);
saeid aslami
  • 101
  • 4