Übergeben von Android-Bitmap-Daten innerhalb von Aktivitäten mit Intent in Android

74

Ich habe eine Bitmap-Variable mit dem Namen bmpActivity1 und möchte die Bitmap an Activity2 senden

Das Folgende ist der Code, den ich benutze, um ihn mit der Absicht zu übergeben.

Intent in1 = new Intent(this, Activity2.class);
in1.putExtra("image",bmp);
startActivity(in1);

Und in Aktivität 2 versuche ich, mit dem folgenden Code auf die Bitmap zuzugreifen

Bundle ex = getIntent().getExtras();
Bitmap bmp2 = ex.getParceable("image");
ImageView result = (ImageView)findViewById(R.Id.imageView1);
result.setImageBitmap(bmp);

Die Anwendung wird ausnahmslos ausgeführt, liefert jedoch nicht das erwartete Ergebnis

adi.zean
quelle
3
Dies ist keine Kopie Ihres Codes, da ich mindestens zwei Tippfehler sehe.
Christine
@Christine: Dies ist wirklich mein Code hehe ,,, aber ich hatte es aus vielen Tutorial ... XP
adi.zean
2
Wie kommt es, dass Sie eine Bitmap bmp2 erstellen und diese mit setImageBitmap (bmp) festlegen? Und sicherlich funktioniert R.Id.imageView1 nicht. Es sollte R.id.imageView1 sein.
Christine
3
Sie können die Bitmap natürlich in eine Datei schreiben und diese Datei in der zweiten Aktivität lesen. Sie können dieselbe Datei verwenden, um sicherzustellen, dass das Bild erhalten bleibt, wenn das Gerät gedreht wird.
Christine
1
Bevor Sie eine Frage stellen, stellen Sie sicher, dass Sie den Code verstehen, den Sie veröffentlichen. Ein einfaches Kopieren und Einfügen von StackOverflow zur Behebung eines Fehlers ist nutzlos. @Christine - Ich wollte das Gleiche über Tippfehler kommentieren.
milosmns

Antworten:

206

Konvertieren Sie es in ein Byte-Array, bevor Sie es der Absicht hinzufügen, senden und dekodieren.

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

Dann in Aktivität 2:

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

bearbeiten

Ich dachte, ich sollte dies mit Best Practice aktualisieren:

In Ihrer ersten Aktivität sollten Sie die Bitmap auf der Festplatte speichern und in der nächsten Aktivität laden. Stellen Sie sicher, dass Sie Ihre Bitmap in der ersten Aktivität recyceln, um sie für die Speicherbereinigung vorzubereiten:

Aktivität 1:

try {
    //Write file
    String filename = "bitmap.png";
    FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE);
    bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);

    //Cleanup
    stream.close();
    bmp.recycle();

    //Pop intent
    Intent in1 = new Intent(this, Activity2.class);
    in1.putExtra("image", filename);
    startActivity(in1);
} catch (Exception e) {
    e.printStackTrace();
}

Laden Sie in Aktivität 2 die Bitmap:

Bitmap bmp = null;
String filename = getIntent().getStringExtra("image");
try {
    FileInputStream is = this.openFileInput(filename);
    bmp = BitmapFactory.decodeStream(is);
    is.close();
} catch (Exception e) {
    e.printStackTrace();
}

Prost!

Zaid Daghestani
quelle
7
Dies löste ein Problem, das ich hatte. Eine Ausnahme wurde ausgelöst, weil "transactionTooLargeException". Beim Senden über extra eine vollständige Bitmap.
Reinherd
bessere Lösung ist hier stackoverflow.com/questions/2459524/…
Nizzy
Ich frage mich nur, wie ich getIntent () in einem Fragment verwenden würde. Ich habe gelesen, dass es nicht möglich ist, aber es muss einen Weg geben.
StillLearningToCode
1
Bytearray = 3 Bilder im Speicher (BMP zuerst, Bytearray, BMP zweitens) Datei = 2 Bilder im Speicher (BMP zuerst, Datei, BMP drittens)
Zaid Daghestani
1
Ich empfehle dringend, die Verwendung von Byte-Arrays zu vermeiden, da Sie die 2-MB-Grenze erreichen und ein Leck haben können. Ich schlage vor, eine temporäre Datei zu erstellen und ihren Pfad durch die Aktivitäten zu verwalten
Trinity
10

Manchmal ist die Bitmap zu groß, um sie zu codieren und zu decodieren oder als Byte-Array in der Absicht zu übergeben. Dies kann entweder zu OOM oder zu einer schlechten Benutzeroberfläche führen.

Ich schlage vor, die Bitmap in eine statische Variable der neuen Aktivität (diejenige, die sie verwendet) einzufügen, die sorgfältig null ist, wenn Sie sie nicht mehr benötigen (dh in onDestroy, aber nur, wenn "isChangingConfigurations" false zurückgibt).

Android-Entwickler
quelle
3

Wir können einfach nur Uri der Bitmap übergeben, anstatt das Bitmap-Objekt zu übergeben. Wenn das Bitmap-Objekt groß ist, führt dies zu Speicherproblemen.

FirstActivity.

intent.putExtra("uri", Uri);

Von SecondActivity erhalten wir eine Bitmap zurück.

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),Uri.parse(uri));
Vignesh Kumar
quelle
IOexception, wenn ich den Bildpfad in uri übergebe. Was könnte der mögliche Grund sein.
Dilip Poudel
1

Kotlin-Code zum absichtlichen Senden einer Bitmap an eine andere Aktivität:

1- in der ersten Aktivität:

          val i = Intent(this@Act1, Act2::class.java)
           var bStream  =  ByteArrayOutputStream()
            bitmap.compress(Bitmap.CompressFormat.PNG, 50, bStream)
            val byteArray = bStream.toByteArray()
            i.putExtra("image", byteArray )
            startActivity(i)

2- In Aktivität zwei (Lesen Sie das Bitmap-Bild):

 var bitmap : Bitmap? =null
    if (intent.hasExtra("image")){
      //convert to bitmap          
        val byteArray = intent.getByteArrayExtra("image")
        bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
    }

3- Wenn Sie es als Hintergrund für eine Ansicht festlegen müssen, z. B. ConstraintLayout oder ...:

 if (bitmap != null) {
     //Convert bitmap to BitmapDrawable
     var bitmapDrawable = BitmapDrawable( resources , bitmap)
      root_constraintLayout.backgroundDrawable = bitmapDrawable
   }
Hamed Jaliliani
quelle
Google hat gerade angekündigt, die Kotlin-Entwicklung wegen mangelnder Benutzeranpassung zu
stoppen
0

Wir können dies auch lösen, ohne Daten absichtlich weiterzugeben. Speichern Sie das Bild einfach im Speicher und laden Sie es in der nächsten Aktivität einfach von diesem Speicherort. Dadurch kann auch verhindert werden, dass ein App-Absturz große Bitmap-Daten übergibt. Hinweis: Sie müssen nicht einmal den Standortpfad an die Absicht übergeben, sich den Pfad merken und ihn verwenden.

murali krish
quelle
0

Ich möchte auch eine Best-Practice-Antwort für diejenigen veröffentlichen, die dies tun möchten (aber möglicherweise die falsche Frage stellen).

Anstatt eine Bitmap weiterzugeben (von der ich annehme, dass Sie sie aus dem Netzwerk heruntergeladen haben, andernfalls hätten Sie bereits einen Dateiverweis darauf), empfehle ich die Verwendung eines Image Loaders wie Universal Image Loader , um ein Bild in eine ImageView herunterzuladen. Sie können es so konfigurieren, dass das Image auf der Festplatte zwischengespeichert wird:

 DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .considerExifParams(true)
                .bitmapConfig(Bitmap.Config.RGB_565)
                .build();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .defaultDisplayImageOptions(defaultOptions)
                .build();

        ImageLoader.getInstance().init(config);

Übergeben Sie jetzt einfach die Bild-URL in Ihrer Absicht und verwenden Sie die UIL, um das Bild zu laden. In Ihrer neu erstellten Aktivität wird das Bild beispielsweise sofort geladen, da es aus dem Cache geladen wird - auch wenn Ihre Bild-URL seit dem Download abgelaufen ist.

Mikro
quelle
-7
Bundle b = new Bundle();
b.putSerializable("Image", Bitmap);
mIntent.putExtras(b);
startActivity(mIntent);
Prashant Mishra
quelle
6
Bitmap ist nicht serialisierbar!
Carnal
Bitte überprüfen Sie diesen Link: stackoverflow.com/questions/5871482/…
Prashant Mishra