Antworten:
Bitmap
implementiert Parcelable
, so dass Sie es immer mit der Absicht übergeben können:
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
und am anderen Ende abrufen:
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
Wenn Sie eine Bitmap als Paket übergeben, wird der Fehler "JAVA BINDER FAILURE" angezeigt. Übergeben Sie die Bitmap als Byte-Array und erstellen Sie sie für die Anzeige in der nächsten Aktivität.
Ich habe meine Lösung hier geteilt:
Wie können Sie Bilder (Bitmaps) zwischen Android-Aktivitäten mithilfe von Bundles übertragen?
Das Übergeben einer Bitmap als parcelbar im Paket 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 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 Aktivität können Sie diese Datei myImage mit folgendem Code in eine Bitmap dekodieren:
//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));
Hinweis Viele Überprüfungen auf Null- und Skalierungs-Bitmaps werden nicht durchgeführt.
openFileOutput
.
Wenn das Bild zu groß ist und Sie es nicht speichern und in den Speicher laden können, sollten Sie nur einen globalen statischen Verweis auf die Bitmap (innerhalb der empfangenden Aktivität) verwenden, der bei onDestory auf null zurückgesetzt wird, nur wenn "isChangingConfigurations" gibt true zurück.
Weil Intent eine Größenbeschränkung hat. Ich verwende ein öffentliches statisches Objekt, um die Bitmap vom Dienst an die Übertragung zu übergeben.
public class ImageBox {
public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>();
}
in meinem Dienst übergeben
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 BroadcastReceiver
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 die Bitmap
zu groß ist. Ich glaube, es ist ein Limit von 1 MB . Das Bitmap
muss in ein anderes Dateiformat wie ein durch a dargestelltes JPG komprimiert werden ByteArray
, dann kann es sicher über ein übergeben werdenIntent
.
Die Funktion ist in einem separaten Thread mit Kotlin Coroutines enthalten, da die Bitmap
Komprimierung verkettet wird, nachdem die Bitmap
aus einer URL erstellt wurde String
. Für die Bitmap
Erstellung ist ein separater Thread erforderlich, um ANR- Fehler (Application Not Responding) zu vermeiden.
toBitmap()
ist eine Kotlin Erweiterungsfunktion der Bibliothek erfordert zur App Abhängigkeit hinzugefügt werden.Bitmap
in JPG komprimieren ByteArray
.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 übergeben 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()
}
}
Es könnte spät sein, kann aber helfen. Deklarieren Sie auf dem ersten Fragment oder der ersten Aktivität 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 machen Sie dies auf der zweiten Klasse / Fragment.
Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;
Ich hoffe es hilft.
Alle oben genannten Lösungen funktionieren bei mir nicht. Das Senden einer Bitmap führt parceableByteArray
ebenfalls zu Fehlern 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:
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()));
In meinem Fall hat der oben erwähnte Weg bei mir nicht funktioniert. Jedes Mal, wenn ich die Bitmap in die Absicht einfügte, wurde die zweite Aktivität nicht gestartet. Das gleiche passierte, als ich die Bitmap als Byte [] übergab.
Ich folgte diesem Link und es funktionierte wie ein Charme und sehr schnell:
package your.packagename
import android.graphics.Bitmap;
public class CommonResources {
public static Bitmap photoFinishBitmap = null;
}
in meiner 1. Tätigkeit:
Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);
und hier ist das onCreate () meiner 2. Aktivität:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bitmap photo = Constants.photoFinishBitmap;
if (photo != null) {
mViewHolder.imageViewerImage.setImageDrawable(new BitmapDrawable(getResources(), photo));
}
}
CommonResources.photoFinishBitmap
anstelle von verwendet haben sollten Constants.photoFinishBitmap
.
URI
oderResourceID
der Bitmap und nicht die Bitmap selbst zu übergeben. Das Übergeben der gesamten Bitmap erfordert viel Speicher. Das Übergeben der URL erfordert sehr wenig Speicher und ermöglicht es jeder Aktivität, die Bitmap nach Bedarf zu laden und zu skalieren.