it-swarm.com.de

Wie kann ich ein Bitmap-Objekt von einer Aktivität an eine andere übergeben?

In meiner Aktivität erstelle ich ein Bitmap-Objekt und muss dann eine weitere Activity, .__ starten. Wie kann ich dieses Bitmap-Objekt aus der Unteraktivität (der zu startenden Aktivität) übergeben?

130
michael

Bitmap implementiert Parcelable, sodass Sie es immer mit der Absicht übergeben können:

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

und hol es am anderen Ende ab:

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

Das Übergeben einer Bitmap als Parcelable führt tatsächlich zu einem Fehler "Java BINDER FAILURE". Versuchen Sie, die Bitmap als Byte-Array zu übergeben und für die nächste Aktivität zu erstellen.

Ich habe meine Lösung hier geteilt:
Wie übergeben Sie Bilder (Bitmaps) zwischen Android-Aktivitäten mithilfe von Bundles?

21
Harlo Holmes

Das Übergeben einer Bitmap als Parceable im Bündel zwischen Aktivitäten ist aufgrund der Größenbeschränkung von Parceable (1 MB) keine gute Idee. Sie können die Bitmap in einer Datei im internen Speicher speichern und die gespeicherte Bitmap in mehreren Aktivitäten abrufen. Hier ist ein Beispielcode.

So speichern Sie eine Bitmap in einer Datei myImage im internen Speicher:

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

In der nächsten Übung können Sie diese Datei myImage mit folgendem Code in eine Bitmap decodieren:

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

Hinweis Eine Überprüfung auf Null und Skalierung von Bitmaps ist nicht erforderlich.

10

Wenn das Bild zu groß ist und Sie es nicht speichern und nicht in den Speicher laden können, sollten Sie nur eine globale statische Referenz auf die Bitmap (innerhalb der Empfangsaktivität) verwenden, die bei onDestory auf null zurückgesetzt wird. gibt wahr zurück.

4

Weil Intent eine Größenbeschränkung hat . Ich benutze ein öffentliches statisches Objekt, um Bitmap vom Dienst an den Broadcast zu übergeben.

public class ImageBox {
    public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>(); 
}

pass in meinem Dienst 

private void downloadFile(final String url){
        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {
                Bitmap b = BitmapFromURL.getBitmapFromURL(url);
                synchronized (this){
                    TaskCount--;
                }
                Intent i = new Intent(ACTION_ON_GET_IMAGE);
                ImageBox.mQ.offer(b);
                sendBroadcast(i);
                if(TaskCount<=0)stopSelf();
            }
        });
    }

Mein Broadcast-Empfänger

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            LOG.d(TAG, "BroadcastReceiver get broadcast");

            String action = intent.getAction();
            if (DownLoadImageService.ACTION_ON_GET_IMAGE.equals(action)) {
                Bitmap b = ImageBox.mQ.poll();
                if(b==null)return;
                if(mListener!=null)mListener.OnGetImage(b);
            }
        }
    };
3
Deyu瑜

Komprimieren und senden Bitmap

Die akzeptierte Antwort stürzt ab, wenn das Bitmap zu groß ist. Ich glaube, es ist ein 1 MB begrenzen. Das Bitmap muss in ein anderes Dateiformat komprimiert werden, z. B. in ein JPG, das durch ein ByteArray dargestellt wird sicher über ein Intent übergeben werden.

Implementierung

Die Funktion ist in einem separaten Thread mit Kotlin Coroutines enthalten, da die Bitmap -Komprimierung verkettet wird, nachdem Bitmap aus einem erstellt wurde URL String. Die Erstellung von Bitmap erfordert einen separaten Thread, um ANR-Fehler zu vermeiden.

Verwendete Konzepte

  • Kotlin Coroutines Notizen .
  • Das Loading, Content, Error (LCE) Muster wird unten verwendet. Bei Interesse können Sie mehr darüber in dieser Vortrag und das Video erfahren.
  • LiveData wird verwendet, um die Daten zurückzugeben. Ich habe meine Lieblingsressource für LiveData in diese Notizen zusammengestellt.
  • In Schritt 3 ist toBitmap() ein Kotlin-Erweiterungsfunktion , das das Hinzufügen dieser Bibliothek zu den App-Abhängigkeiten erfordert.

Code

1. Komprimieren Sie Bitmap zu JPGByteArray, nachdem es erstellt wurde.

Repository.kt

suspend fun bitmapToByteArray(url: String) = withContext(Dispatchers.IO) {
    MutableLiveData<Lce<ContentResult.ContentBitmap>>().apply {
        postValue(Lce.Loading())
        postValue(Lce.Content(ContentResult.ContentBitmap(
            ByteArrayOutputStream().apply {
                try {                     
                    BitmapFactory.decodeStream(URL(url).openConnection().apply {
                        doInput = true
                        connect()
                    }.getInputStream())
                } catch (e: IOException) {
                   postValue(Lce.Error(ContentResult.ContentBitmap(ByteArray(0), "bitmapToByteArray error or null - ${e.localizedMessage}")))
                   null
                }?.compress(CompressFormat.JPEG, BITMAP_COMPRESSION_QUALITY, this)
           }.toByteArray(), "")))
        }
    }

ViewModel.kt

//Calls bitmapToByteArray from the Repository
private fun bitmapToByteArray(url: String) = liveData {
    emitSource(switchMap(repository.bitmapToByteArray(url)) { lce ->
        when (lce) {
            is Lce.Loading -> liveData {}
            is Lce.Content -> liveData {
                emit(Event(ContentResult.ContentBitmap(lce.packet.image, lce.packet.errorMessage)))
            }
            is Lce.Error -> liveData {
                Crashlytics.log(Log.WARN, LOG_TAG,
                        "bitmapToByteArray error or null - ${lce.packet.errorMessage}")
            }
        }
    })
}

2. Übergeben Sie das Bild als ByteArray über Intent.

In diesem Beispiel wird es von einem Fragment an einen Dienst übergeben. Es ist das gleiche Konzept, wenn es zwischen zwei Aktivitäten geteilt wird.

Fragment.kt

ContextCompat.startForegroundService(
    context!!,
    Intent(context, AudioService::class.Java).apply {
        action = CONTENT_SELECTED_ACTION
        putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
    })

3. Konvertieren Sie ByteArray zurück zu Bitmap.

Utils.kt

fun ByteArray.byteArrayToBitmap(context: Context) =
    run {
        BitmapFactory.decodeByteArray(this, BITMAP_OFFSET, size).run {
            if (this != null) this
            // In case the Bitmap loaded was empty or there is an error I have a default Bitmap to return.
            else AppCompatResources.getDrawable(context, ic_coinverse_48dp)?.toBitmap()
        }
    }
1
Adam Hurwitz

Alle oben genannten Lösungen funktionieren für mich nicht. Das Senden einer Bitmap als parceableByteArray erzeugt auch den Fehler Android.os.TransactionTooLargeException: data parcel size.

Lösung

  1. Die Bitmap wurde im internen Speicher gespeichert als:
public String saveBitmap(Bitmap bitmap) {
        String fileName = "ImageName";//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;
    }
  1. und senden Sie putExtra(String) als
Intent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
  1. und erhalte es in anderen Aktivitäten als:
if(getIntent() != null){
  try {
           src = BitmapFactory.decodeStream(openFileInput("myImage"));
       } catch (FileNotFoundException e) {
            e.printStackTrace();
      }

 }


0
Ali Tamoor

Sie können eine Bitmap-Übertragung erstellen. Versuche dies....

In der ersten Klasse:

1) Erstellen Sie:

private static Bitmap bitmap_transfer;

2) Erstellen Sie Getter und Setter

public static Bitmap getBitmap_transfer() {
    return bitmap_transfer;
}

public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
    bitmap_transfer = bitmap_transfer_param;
}

3) Stellen Sie das Bild ein:

ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());

Dann in der zweiten Klasse:

ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));
0

Es könnte zu spät sein, kann aber helfen. Zum ersten Fragment oder zur ersten Aktivität deklarieren Sie eine Klasse ... zum Beispiel

   @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        description des = new description();

        if (requestCode == PICK_IMAGE_REQUEST && data != null && data.getData() != null) {
            filePath = data.getData();
            try {
                bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), filePath);
                imageView.setImageBitmap(bitmap);
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
                constan.photoMap = bitmap;
            } catch (IOException e) {
                e.printStackTrace();
            }
       }
    }

public static class constan {
    public static Bitmap photoMap = null;
    public static String namePass = null;
}

Dann auf der zweiten Klasse/Fragment dies tun ..

Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;

Ich hoffe es hilft.

0
ANTONY MWANGI