Jawaban:
Bitmap
mengimplementasikan Parcelable
, sehingga Anda selalu bisa melewatinya dengan maksud:
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
dan mengambilnya di ujung yang lain:
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
Sebenarnya, melewatkan bitmap sebagai Parcelable akan menghasilkan kesalahan "JAVA BINDER FAILURE". Coba lewati bitmap sebagai array byte dan buat untuk ditampilkan di aktivitas selanjutnya.
Saya membagikan solusi saya di sini:
bagaimana Anda mengirimkan gambar (bitmap) antara aktivitas Android menggunakan bundel?
Melewati bitmap sebagai parceable dalam bundel di antara aktivitas bukanlah ide yang baik karena batasan ukuran Parceable (1mb). Anda dapat menyimpan bitmap dalam file di penyimpanan internal dan mengambil bitmap yang disimpan dalam beberapa aktivitas. Ini beberapa contoh kode.
Untuk menyimpan bitmap dalam file myImage di penyimpanan internal:
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;
}
Kemudian pada aktivitas selanjutnya Anda dapat mendekode file myImage ke bitmap menggunakan kode berikut:
//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));
Catatan Banyak memeriksa null dan menskalakan bitmap dihentikan.
openFileOutput
.
Jika gambar terlalu besar dan Anda tidak dapat menyimpan & memuatnya ke penyimpanan, Anda harus mempertimbangkan hanya menggunakan referensi statis global ke bitmap (di dalam aktivitas penerima), yang akan diatur ulang ke nol pada onDestory, hanya jika "isChangingConfigurations" mengembalikan true.
Karena Intent memiliki batas ukuran. Saya menggunakan objek statis publik untuk melakukan pass bitmap dari layanan ke siaran ....
public class ImageBox {
public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>();
}
lulus dalam layanan saya
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();
}
});
}
BroadcastReceiver saya
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
Jawaban yang diterima akan macet ketika Bitmap
terlalu besar. Saya percaya ini adalah batas 1MB . The Bitmap
harus dikompresi ke dalam format file yang berbeda seperti JPG diwakili oleh ByteArray
, maka dapat dengan aman melewati melaluiIntent
.
Fungsi ini terkandung dalam utas terpisah menggunakan Kotlin Coroutines karena Bitmap
kompresi dirantai setelah Bitmap
dibuat dari url String
. The Bitmap
penciptaan membutuhkan thread terpisah untuk menghindari Aplikasi Tidak Menanggapi (PPA) kesalahan.
toBitmap()
adalah fungsi ekstensi Kotlin yang membutuhkan pustaka yang akan ditambahkan ke dependensi aplikasi.Bitmap
ke JPG ByteArray
setelah itu dibuat.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(), "")))
}
}
LihatModel.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
melalui Intent
.Dalam sampel ini, ini diteruskan dari Fragmen ke Layanan . Itu adalah konsep yang sama jika dibagikan di antara dua Kegiatan .
Fragment.kt
ContextCompat.startForegroundService(
context!!,
Intent(context, AudioService::class.java).apply {
action = CONTENT_SELECTED_ACTION
putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
})
ByteArray
kembali ke 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()
}
}
Mungkin terlambat tetapi bisa membantu. Pada fragmen atau aktivitas pertama, deklarasikan sebuah kelas ... misalnya
@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;
}
Kemudian pada kelas kedua / fragmen lakukan ini ..
Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;
Semoga ini bisa membantu.
Semua solusi di atas tidak bekerja untuk saya, Mengirim bitmap parceableByteArray
juga menghasilkan kesalahan android.os.TransactionTooLargeException: data parcel size
.
Larutan
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)
sebagaiIntent 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();
}
}
Anda dapat membuat transfer bitmap. coba ini....
Di kelas pertama:
1) Buat:
private static Bitmap bitmap_transfer;
2) Buat pengambil dan penyetel
public static Bitmap getBitmap_transfer() {
return bitmap_transfer;
}
public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
bitmap_transfer = bitmap_transfer_param;
}
3) Atur gambar:
ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());
Kemudian, di kelas kedua:
ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));
Dalam kasus saya, cara yang disebutkan di atas tidak berhasil untuk saya. Setiap kali saya menaruh bitmap dalam maksud, aktivitas ke-2 tidak dimulai. Hal yang sama terjadi ketika saya melewati bitmap sebagai byte [].
Saya mengikuti tautan ini dan itu bekerja seperti pesona dan sangat cepat:
package your.packagename
import android.graphics.Bitmap;
public class CommonResources {
public static Bitmap photoFinishBitmap = null;
}
dalam kegiatan pertama saya:
Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);
dan ini adalah onCreate () dari Aktivitas ke-2 saya:
@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
bukan Constants.photoFinishBitmap
.
URI
atauResourceID
bitmap dan bukan bitmap itu sendiri. Melewati seluruh bitmap membutuhkan banyak memori. Melewati URL membutuhkan sedikit memori dan memungkinkan setiap aktivitas memuat dan menskalakan bitmap sesuai kebutuhan.