【问题标题】:Passing Bitmap between two activities [duplicate]在两个活动之间传递位图[重复]
【发布时间】:2012-10-06 03:50:53
【问题描述】:

我正在开发一个绘画应用程序,我想在其中将位图图像从一个活动传递到另一个活动,但项目没有响应。我将相对布局屏幕截图转换为位图并通过 Intent 传递,但问题没有解决。这是我的代码....

绘图活动

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;
    }
 }

定位报告

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

【问题讨论】:

    标签: android android-layout


    【解决方案1】:

    您可以简单地尝试以下 -

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

    并且,在Second.class

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

    看看here如果你想在发送到下一个活动之前压缩你的Bitmap,看看下面 -

    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);
    

    在你的下一个活动中 -

    if(getIntent().hasExtra("byteArray")) {
        ImageView previewThumbnail = new ImageView(this);
        Bitmap b = BitmapFactory.decodeByteArray(
                        getIntent().getByteArrayExtra("byteArray"),0,getIntent()
                        .getByteArrayExtra("byteArray").length);        
        previewThumbnail.setImageBitmap(b);
    }
    

    【讨论】:

    • 我想使用 Mode.CLEAR 擦除位图。我想将默认颜色(黑色)更改为开发人员定义的颜色。你能帮我吗?? @Spk
    • 谢谢你。如果你有任何想法。告诉我怎么做
    【解决方案2】:

    我认为在大多数情况下,可以将位图放在静态引用上,当接收活动不再需要它时,该引用应该为空。

    这样,速度非常快,不需要转换或编码和解码。它也不会留下痕迹。

    【讨论】:

      【解决方案3】:

      有很多方法:

      1)

      Bitmap 实现 Parcelable,因此您始终可以在 Intent 中传递它:

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

      并在另一端检索它:

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

      2)

      在将其添加到 Intent、发送出去和解码之前将其转换为 Byte 数组。

      //转换为字节数组

      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);
      

      那么在活动 2 中:

      byte[] byteArray = getIntent().getByteArrayExtra("image");
      Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
      

      【讨论】:

      • 第一个解决方案抛出“失败的活页夹事务”。
      【解决方案4】:

      我在this SO 帖子中回答了类似的问题。我的解决方案会将图像保存在其他应用程序无法访问的设备的内部存储中(在无根手机上)。然后我们可以简单地解码文件并在 imageview 中显示它。它可以防止 TranscationTooLarge 异常,因为您不能超过 1mb 的传递包限制。

      【讨论】:

        【解决方案5】:

        如果您的图像是静态的并且在可绘制文件夹等中因此将位图从意图发送到下一个活动非常昂贵(对于机器:))所以现在最好的方法是首先在strings.xml 中创建string-array 就像这里一样。

        <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>
        

        然后在您的活动中获取与上面声明的imagesthat 数组相关的图像列表。

        1:-声明TypeArray typeArray的实例

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

        3:-声明你的列表并一个一个地添加每个项目 ->

             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:-当然现在你会在你的ArrayAdapter中设置这个列表

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

        5:-将点击的位图图像发送到您的下一个活动

         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:-接收您的位图 ID 并获取您的位图图像

        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);
        
        
            }
        }
        

        【讨论】:

          【解决方案6】:

          在你的 logcat 中说明

          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)
          

          您的位图在传递给 ImageActivity 之前已被回收。您可以将位图设为静态,这样它就不会被回收。

          【讨论】:

            【解决方案7】:

            您可以使用 bundle 将位图从一个活动传递到另一个活动

            将您的图像添加到字节数组中:

            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);
            

            并在从 bundle 中创建接收器活动时获取您的图像

            【讨论】:

              【解决方案8】:

              苦苦寻找,终于在https://eazyprogramming.blogspot.com/2013/01/passing-image-between-activities.html#comment-form找到答案

              在第一个活动中

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

              在第二个活动中:

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

              另一种方法: 在第一个活动中:

              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); 
              

              在第二个活动中:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-05-12
                • 1970-01-01
                • 1970-01-01
                • 2018-03-25
                • 1970-01-01
                • 1970-01-01
                • 2021-05-30
                相关资源
                最近更新 更多