Android上在两个Activity之间传递Bitmap对象

简介: Android上在两个Activity之间传递Bitmap对象

Android上在两个Activity之间传递Bitmap对象


因为我做Android应用的时间不长,所以当我第一次在android之间传递Bitmap对象的时候我直接用了Intent.putExtra的方法实现了,当时我选择的是一张图像的ROI区域,所以工作的很好,但是当我尝试将整个图片做为Bitmap对象传到另外一个Activity中的时候总是得到一个错误fatal bind error我当时很郁闷了好久,后来google才发现是这样传递Bitmap对象的方式不对,Activity之间传递Bitmap有大小限制,而且这个大小限制很小,512x512的图片肯定会得到我上述的这个错误,于是我想到了先保存到SD卡上然后传递路径的方法,但是SD卡属于外部存储,可能不是特别方便,后来看到有人通过内部存储方式实现了在两个Activity之间传递Bitmap对象以及其它支持串行化的Java对象,我觉得很好,所以就写了这篇博客。关键点有如下:


1.  HTTP客户端下载图片,通过ImageView对象显示


2.  把ImageView上的Bitmap对象从当前Activity传递到另外一个


Activity中并显示出来


3.  基于串行化传递Java对象数据



首先看我是怎么实现HTTP客户端下载图片,通过异步Task接口实现HTTP客户端下载图片并通过Handler来更新ImageView,代码如下:

package com.example.sharedemo;
 
import java.io.IOException;
import java.io.InputStream;
 
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
 
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
 
public class ImageLoadTask extends AsyncTask<String, Void, Bitmap> {
  private Handler handler;
 
  public ImageLoadTask(Handler handler) {
    this.handler = handler;
  }
 
  protected void onPostExecute(Bitmap bitmap) {
    Message msg = new Message();
    msg.obj = bitmap;
    handler.sendMessage(msg);
  }
 
  @Override
  protected Bitmap doInBackground(String... urls) {
    Bitmap bitmap = null;
    // create HTTP client
    HttpClient httpclient = new DefaultHttpClient();
    try {
      // GET request
      Log.i("image-url", urls[0]);
      HttpGet httpRequest = new HttpGet(urls[0]);
      HttpResponse httpResponse = httpclient.execute(httpRequest);
      if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
        // get entity from response
        HttpEntity httpEntity = httpResponse.getEntity();
        // read stream
        InputStream is = httpEntity.getContent();
        bitmap = BitmapFactory.decodeStream(is);
        is.close();
        Log.i("image", "already get the image by url : " + urls[0]);
      }
 
    } catch (ClientProtocolException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      httpclient.getConnectionManager().shutdown();
    }
    return bitmap;
  }
 
}

在当前的Activity中通过按钮上的事件响应实现切换View到对应的Activity中去,同时实现Java串行化数据传递。MainActivity的代码如下:

package com.example.sharedemo;
 
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
 
public class MainActivity extends Activity implements OnClickListener{
  public final static String SHARE_BITMAP_COMMAND = "share-image";
  public final static String SHARE_TEXT_DATA_COMMAND = "share-text-data";
  private Handler handler;
 
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    setupOnClickListener();
  }
 
  private void setupOnClickListener() {
    Button bitmapBtn = (Button)this.findViewById(R.id.bitmapShareBtn);
    bitmapBtn.setTag(SHARE_BITMAP_COMMAND);
    bitmapBtn.setOnClickListener(this);
    Button textDataBtn = (Button)this.findViewById(R.id.mapShareBtn);
    textDataBtn.setTag(SHARE_TEXT_DATA_COMMAND);
    textDataBtn.setOnClickListener(this);
    final ImageView imageView = (ImageView)this.findViewById(R.id.imageView1);
    
    handler = new Handler()
    {
      public void handleMessage(Message msg) {
        Bitmap bitmap = (Bitmap)msg.obj;
        if(bitmap != null)
        {
          /*
          // 为防止原始图片过大导致内存溢出,这里先缩小原图显示,然后释放原始Bitmap占用的内存
          Bitmap smallBitmap = zoomBitmap(bitmap, bitmap.getWidth()/ 5, bitmap.getHeight() / 5);
          // 释放资源
          bitmap.recycle();
          // 显示图片
          imageView.setImageBitmap(smallBitmap);
          imageView.invalidate();
          */
          imageView.setImageBitmap(bitmap);
        }
      }
    };
    ImageLoadTask task = new ImageLoadTask(handler);
    task.execute("https://img-blog.csdn.net/20150607143208238");
  }
  
  public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();
    Matrix matrix = new Matrix();
    float scaleWidth = ((float) width / w);
    float scaleHeight = ((float) height / h);
    matrix.postScale(scaleWidth, scaleHeight); // 不改变原来图像大小
    Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
    return newbmp;
  }
 
  @Override
  public void onClick(View v) {
    Object tag = v.getTag();
    Log.i("command", tag.toString());
    if(SHARE_BITMAP_COMMAND.equals(tag))
    {
      Intent intent = new Intent(this.getApplicationContext(), ImageProcessActivity.class);
      ImageView imageView = (ImageView)this.findViewById(R.id.imageView1);
      Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
      intent.putExtra("selectedImage", bitmap);
      intent.putExtra("name", "lena");
      intent.putExtra("description", "超级大美女");
      this.startActivity(intent);     
    }
    else if(SHARE_TEXT_DATA_COMMAND.equals(tag))
    {
      Intent intent = new Intent(this.getApplicationContext(), ImageProcessActivity.class);
      ImageView imageView = (ImageView)this.findViewById(R.id.imageView1);
      Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
      // save it first then pass URI
      ImageInfoBean dto = new ImageInfoBean();
      String uri = createImageFromBitmap(bitmap);
      dto.setDescription("超级大美女");
      dto.setName("lena");
      dto.setUri(uri);
      
      intent.putExtra("tiger", dto);
      this.startActivity(intent); 
    }
  }
  
  public String createImageFromBitmap(Bitmap bitmap) {
      String fileName = "myImage";
      try {
          ByteArrayOutputStream bytes = new ByteArrayOutputStream();
          bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
          FileOutputStream fo = openFileOutput(fileName, Context.MODE_PRIVATE);
          fo.write(bytes.toByteArray());
          fo.close();
      } catch (Exception e) {
          e.printStackTrace();
          fileName = null;
      }
      Log.i("fileName", fileName);
      return fileName;
  }
}

对应另外一个Activity中实现读取与组装Bitmap对象显示的代码如下:

package com.example.sharedemo;
 
import java.io.FileNotFoundException;
 
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
 
public class ImageProcessActivity extends Activity {
 
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.share_info);
    backFillData();
  }
 
  private void backFillData() {
    Object obj = this.getIntent().getExtras().get("tiger");
    ImageView imageView = (ImageView)this.findViewById(R.id.imageView1);
    TextView text1 = (TextView)this.findViewById(R.id.textView1);
    TextView text2 = (TextView)this.findViewById(R.id.textView2);
    try {
      if(obj != null && obj instanceof ImageInfoBean)
      {
        ImageInfoBean dto = (ImageInfoBean)obj;
        Bitmap bitmap = BitmapFactory.decodeStream(this.openFileInput(dto.getUri()));
        imageView.setImageBitmap(bitmap);
        imageView.invalidate(); // refresh
        
        text1.setText("名称: " + dto.getName());
        text2.setText("描述: " + dto.getDescription());
        return;
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    
    Bitmap bitmap = (Bitmap) this.getIntent().getParcelableExtra("selectedImage");
    String name = this.getIntent().getExtras().getString("name");
    String description = this.getIntent().getExtras().getString("description");
    if(bitmap != null)
    {
      imageView.setImageBitmap(bitmap);
      imageView.invalidate(); // refresh
    }
    if(name != null)
    {
      text1.setText("名称: " + name);
    }
    if(description != null)
    {
      text2.setText("描述: " + description);
    }
  }
 
}

对应的Java串行化对象类代码如下:

package com.example.sharedemo;
 
import java.io.Serializable;
 
public class ImageInfoBean implements Serializable {
  /**
   * 
   */
  private static final long serialVersionUID = 1L;
 
  public String getName() {
    return name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
 
  public String getDescription() {
    return description;
  }
 
  public void setDescription(String description) {
    this.description = description;
  }
 
  public String getUri() {
    return uri;
  }
 
  public void setUri(String uri) {
    this.uri = uri;
  }
 
  private String name;
  private String description;
  private String uri;
 
}

最后声明:

别忘记在Manifest文件添加网络访问的权限

<uses-permission android:name="android.permission.INTERNET"/>

第一个按钮【传递图片】将会演示我遇到错误,第二按钮【传递文本数据】

将会演示正确的处理结果,显示如下:

相关文章
|
24天前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
70 6
|
25天前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
24 3
|
25天前
|
缓存 前端开发 Android开发
Android实战之如何截取Activity或者Fragment的内容?
本文首发于公众号“AntDream”,介绍了如何在Android中截取Activity或Fragment的屏幕内容并保存为图片。包括截取整个Activity、特定控件或区域的方法,以及处理包含RecyclerView的复杂情况。
18 3
|
25天前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
17 0
|
2月前
|
Android开发 开发者
Android面试之Activity启动流程简述
每个Android开发者都熟悉的Activity,但你是否了解它的启动流程呢?本文将带你深入了解。启动流程涉及四个关键角色:Launcher进程、SystemServer的AMS、应用程序的ActivityThread及Zygote进程。核心在于AMS与ActivityThread间的通信。文章详细解析了从Launcher启动Activity的过程,包括通过AIDL获取AMS、Zygote进程启动以及ActivityThread与AMS的通信机制。接着介绍了如何创建Application及Activity的具体步骤。整体流程清晰明了,帮助你更深入理解Activity的工作原理。
50 0
|
6月前
|
数据库 Android开发 开发者
Android基础知识:请解释Activity的生命周期。
Android基础知识:请解释Activity的生命周期。
75 2
|
5月前
|
Android开发 UED
Android Activity的生命周期详解
Android Activity的生命周期详解
|
6月前
|
Android开发
Android Studio APP开发入门之活动Activity中启停活动页面的讲解及实战(附源码,包括Activity的启动结束、生命周期、跳转等)
Android Studio APP开发入门之活动Activity中启停活动页面的讲解及实战(附源码,包括Activity的启动结束、生命周期、跳转等)
121 0
|
Android开发
Android 中Activity和Fragment生命周期的具体变化详解
Android 中Activity和Fragment生命周期的具体变化详解
194 0
|
Android开发
Android中下拉通知栏,Activity会走哪些生命周期?
我们就可以做一个总结:当前Activity中,下拉通知栏,是不走任何生命周期的。
238 0