web-dev-qa-db-ja.com

バンドルを使用してAndroidアクティビティ間で画像(ビットマップ)をどのように渡しますか?

例のように、ギャラリーから画像を選択し、BitMapとして取得するアクティビティがあるとします: here

次に、このBitMapを渡して、別のアクティビティのImageViewで使用するようにします。アクティビティ間でバンドルを渡すことができますが、このBitMapをバンドルに保存するにはどうすればよいですか?

または私が取るべき別のアプローチがありますか?

50
damonkashu

別のアプローチを強くお勧めします。

本当にやりたい場合は可能ですが、メモリを大量に消費し、速度も遅くなります。古い携帯電話と大きなビットマップを使用している場合、機能しない可能性があります。たとえば、intent.putExtra("data", bitmap)のように、余分なものとして渡すことができます。ビットマップはParcelableを実装しているので、追加することができます。同様に、バンドルにはputParcelableがあります。

アクティビティ間で渡したい場合は、ファイルに保存します。これはより効率的で、作業量が少なくなります。 MODE_PRIVATEを使用して、他のアプリからアクセスできないプライベートファイルをデータフォルダーに作成できます。

48
EboMike

Parcelableとして渡すと、Java BINDER FAILUREエラーが発生します。したがって、解決策は次のとおりです。ビットマップが小さい場合、たとえばサムネイル、パスバイト配列として、次のアクティビティで表示するビットマップを作成します。

呼び出しアクティビティで...

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);
}
41
Harlo Holmes

@EboMikeが示唆するように、ビットマップをmyImageという名前のファイルに保存しました。これは、他のアプリにアクセスできないアプリケーションの内部ストレージにあります。その部分のコードは次のとおりです。

public String createImageFromBitmap(Bitmap bitmap) {
    String fileName = "myImage";//no .png or .jpg needed
    try {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
        FileOutputStream fo = openFileOutput(fileName, Context.MODE_PRIVATE);
        fo.write(bytes.toByteArray());
        // remember close file output
        fo.close();
    } catch (Exception e) {
        e.printStackTrace();
        fileName = null;
    }
    return fileName;
}

次のアクティビティでは、次のコードを使用して、このファイルmyImageをビットマップにデコードできます。

Bitmap bitmap = BitmapFactory.decodeStream(context
                    .openFileInput("myImage"));//here context can be anything like getActivity() for fragment, this or MainActivity.this

nullのチェックとビットマップのスケーリングは省略されています。

22

アクティビティ

Activites間でビットマップを渡すには

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

そしてActivityクラスでは

Bitmap bitmap = getIntent().getParcelableExtra("bitmap");

フラグメント

フラグメント間でビットマップを渡すには

SecondFragment fragment = new SecondFragment();
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", bitmap);
fragment.setArguments(bundle);

SecondFragment内で受信するには

Bitmap bitmap = getArguments().getParcelable("bitmap");

大きなビットマップの転送(ビットマップの圧縮)

失敗したバインダートランザクションを取得している場合、これは、1つのアクティビティから別のアクティビティに大きな要素を転送することにより、バインダートランザクションバッファーを超えていることを意味します。

その場合、ビットマップをバイトの配列として圧縮してから、別のアクティビティで圧縮解除する必要があります、このように

FirstActivity

Intent intent = new Intent(this, SecondActivity.class);

ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPG, 100, stream);
byte[] bytes = stream.toByteArray(); 
intent.putExtra("bitmapbytes",bytes);

SecondActivity

byte[] bytes = getIntent().getByteArrayExtra("bitmapbytes");
Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
5
capt.swag

first.Javaで

Intent i = new Intent(this, second.class);
                    i.putExtra("uri",uri);
                    startActivity(i);

second.Java

Bundle bd = getIntent().getExtras();
        Uri uri = bd.getParcelable("uri");
        Log.e("URI", uri.toString());
        try {
            Bitmap bitmap = Media.getBitmap(this.getContentResolver(), uri);
            imageView.setImageBitmap(bitmap);

        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
2
Jahh

ビットマップは Parcelable ですので、[putExtra(String、Parcelable)] [2]メソッドを使用して追加できますが、ベストプラクティスであるかどうかはわかりません。サイズの大きいデータの場合は、単一の場所と両方のアクティビティからの使用。

[2]: http://developer.Android.com/reference/Android/content/Intent.html#putExtra(Java.lang.String 、Android.os.Parcelable)

2
Sudar Nimalan

次のアクティビティに意図したいところからこのコードを書きます。

    yourimageView.setDrawingCacheEnabled(true); 
    Drawable drawable = ((ImageView)view).getDrawable(); 
    Bitmap bitmap = imageView.getDrawingCache();
    Intent intent = new Intent(getBaseContext(), NextActivity.class);
    intent.putExtra("Image", imageBitmap);

NextActivity.classのonCreate関数で

Bitmap hotel_image;
Intent intent = getIntent();
hotel_image= intent.getParcelableExtra("Image");
1
Wajid khan

トランザクションバインダーの1 MBの制限を超えないように、ビットマップを少しスケーリングし直す必要がありました。 400を画面に適応させることも、動的にすることもできます。これは単なる例です。それはうまく機能し、品質は素晴らしいです。また、画像を保存してからロードするよりもはるかに高速ですが、サイズに制限があります。

public void loadNextActivity(){
    Intent confirmBMP = new Intent(this,ConfirmBMPActivity.class);

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    Bitmap bmp = returnScaledBMP();
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);

    confirmBMP.putExtra("Bitmap",bmp);
    startActivity(confirmBMP);
    finish();

}
public Bitmap returnScaledBMP(){
    Bitmap bmp=null;
    bmp = tempBitmap;
    bmp = createScaledBitmapKeepingAspectRatio(bmp,400);
    return bmp;

}

次のコードでnextActivityのbmpを回復した後:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_confirmBMP);
    Intent intent = getIntent();
    Bitmap bitmap = (Bitmap) intent.getParcelableExtra("Bitmap");

}

私の答えが何らかの形で役立つことを願っています。あいさつ

1
Jan Ziesse

このようなバンドルを使用せずに短い画像を渡すことができますこれは送信者.classファイルのコードです

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher;
Intent intent = new Intent();
Intent.setClass(<Sender_Activity>.this, <Receiver_Activity.class);
Intent.putExtra("Bitmap", bitmap);
startActivity(intent);

これは、レシーバークラスファイルコードです。

Bitmap bitmap = (Bitmap)this.getIntent().getParcelableExtra("Bitmap");
ImageView viewBitmap = (ImageView)findViewById(R.id.bitmapview);
viewBitmap.setImageBitmap(bitmap);

圧縮する必要はありません。それでおしまい

1
Abdul Qadir