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?
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");
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?
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.
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.
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);
}
}
};
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.
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.
toBitmap()
ein Kotlin-Erweiterungsfunktion , das das Hinzufügen dieser Bibliothek zu den App-Abhängigkeiten erfordert.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}")
}
}
})
}
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)
})
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()
}
}
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
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;
}
putExtra(String)
alsIntent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
if(getIntent() != null){
try {
src = BitmapFactory.decodeStream(openFileInput("myImage"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
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()));
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.