Wie kann ich übergeben Sie ein Bitmap-Objekt von einer Aktivität zur anderen
-
20-09-2019 - |
Frage
In meiner Tätigkeit erstelle ich eine Bitmap
Objekt und dann brauche ich zum starten eines anderen Activity
,
Wie kann ich diese übergeben Bitmap
Objekt aus der sub-Aktivität (die eine, die ist gehen zu gestartet werden)?
Lösung
Bitmap
Geräte Parcelable
, so konnte man immer es passiert, mit der Absicht:
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
und rufen sie am anderen Ende:
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
Andere Tipps
Eigentlich wird eine Bitmap als Parcel vorbei führen zu einem „JAVA BINDER FAILURE“ Fehlern. Versuchen Sie das Bestehen die Bitmap als Byte-Array und Gebäude es für die Anzeige in der nächsten Aktivität.
ich meine Lösung hier geteilt:
wie geben Sie Bilder ( Bitmaps) zwischen android-Aktivitäten Bündel mit?
Passsing Bitmap als parceable in Bündel zwischen Aktivität ist keine gute Idee, weil die Größenbeschränkung von Parceable (1MB). Sie können die Bitmap in einer Datei im internen Speicher speichern und die gespeicherte Bitmap in mehreren Aktivitäten abzurufen. Hier ist ein Beispielcode.
Zum Speichern von Bitmap in einer Datei myImage in internen Speichern:
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;
}
Dann in der nächsten Aktivität können Sie diese Datei myImage in einem Bitmap dekodieren folgenden Code:
//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));
Hinweis Eine Menge für null Überprüfung und Bitmap Skalierung wird ommited.
Wenn das Bild zu groß ist und man kann es auf die Speicher nicht speichern und laden, sollten Sie nur einen globalen statischen Verweis auf die Bitmap mit (innerhalb der Aufnahmeaktivität), die wieder auf null auf onDestory sein wird, nur dann, wenn "isChangingConfigurations" true zurück.
Da Intent Größenbeschränkung. Ich benutze öffentliches statisches Objekt Pass Bitmap aus dem Dienst zu Sendung zu tun ....
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();
}
});
}
Meine 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);
}
}
};
Komprimieren und Versenden Bitmap
Die akzeptierte Antwort wird Abstürzen, wenn die Bitmap
zu groß. Ich glaube, es ist ein 1 MB Grenze.Die Bitmap
werden muss, komprimiert in ein anderes Dateiformat wie ein JPG vertreten durch ByteArray
, dann kann es sicher passiert über ein Intent
.
Umsetzung
Die Funktion ist, die in einem separaten thread verwenden Kotlin Coroutinen da die Bitmap
Kompression ist angekettet, nachdem die Bitmap
erstellt von einer url String
.Die Bitmap
Erstellung erfordert einen separaten thread, um zu vermeiden, Anwendung Nicht mehr Reagiert (ANR) Fehler.
Konzepte
- Kotlin Coroutinen notes.
- Die Be -, Content -, Fehler - (LCE) Muster unten verwendet wird.Bei Interesse können Sie mehr dazu erfahren Sie in dieser Vortrag und video.
- LiveData wird verwendet, um die Daten zurückzugeben.Das ich zusammengestellt habe meine Lieblings LiveData Ressource diese Hinweise.
- In Schritt 3,
toBitmap()
ist ein Kotlin-Erweiterung Funktion die Forderung, dass-Bibliothek Hinzugefügt werden die app-Abhängigkeiten.
Code
1.Komprimieren Bitmap
zu JPG ByteArray
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.Pass-Bild als ByteArray
über eine Intent
.
In diesem Beispiel ist es der übergang von Fragment zu einem Service.Es ist das gleiche Konzept, wenn geteilt zwischen zwei Aktivitäten.
Fragment.kt
ContextCompat.startForegroundService(
context!!,
Intent(context, AudioService::class.java).apply {
action = CONTENT_SELECTED_ACTION
putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
})
3.Konvertieren ByteArray
zurück 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 sein, spät, aber helfen kann. Auf dem ersten Fragmente oder Aktivität tun, um eine Klasse deklariert ... 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 tun, um diese ..
Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;
Hope es hilft.
Sie können eine Bitmap-Übertragung erstellen. try this ....
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:
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()));
Alle oben genannten Lösungen nicht funktioniert für mich, Senden Bitmap als parceableByteArray
auch Fehler android.os.TransactionTooLargeException: data parcel size
erzeugt.
Lösung
- Saved die Bitmap in internen Speicher wie:
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;
}
- und sendet in
putExtra(String)
als
Intent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
- und empfängt sie in einer anderen Aktivität als:
if(getIntent() != null){
try {
src = BitmapFactory.decodeStream(openFileInput("myImage"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
In meinem Fall erwähnte die Möglichkeit, oben nicht für mich gearbeitet. Jedes Mal, wenn ich die Bitmap in der Absicht setzte, hat die zweite Aktivität nicht gestartet werden. Das gleiche passiert, wenn ich die Bitmap als byte [] übergeben.
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 meinem ersten acitiviy:
Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);
und hier ist die onCreate () meiner zweiten 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));
}
}