Respuestas:
Bitmap
implementa Parcelable
, por lo que siempre puede pasarlo con la intención:
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
y recuperarlo en el otro extremo:
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
En realidad, pasar un mapa de bits como Parcelable dará como resultado un error de "FALLA DE ENLACE DE JAVA". Intente pasar el mapa de bits como una matriz de bytes y compílelo para mostrarlo en la siguiente actividad.
Compartí mi solución aquí:
¿cómo pasas imágenes (mapas de bits) entre las actividades de Android usando paquetes?
Pasar el mapa de bits como parceable en el paquete entre actividades no es una buena idea debido a la limitación de tamaño de Parceable (1mb). Puede almacenar el mapa de bits en un archivo en almacenamiento interno y recuperar el mapa de bits almacenado en varias actividades. Aquí hay un código de muestra.
Para almacenar un mapa de bits en un archivo myImage en almacenamiento interno:
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;
}
Luego, en la siguiente actividad, puede decodificar este archivo myImage en un mapa de bits utilizando el siguiente código:
//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));
Nota Se omite mucha comprobación de mapas de bits nulos y de escala.
openFileOutput
.
Si la imagen es demasiado grande y no puede guardarla y cargarla en el almacenamiento, debería considerar usar una referencia global estática al mapa de bits (dentro de la actividad de recepción), que se restablecerá a nulo en onDestory, solo si "isChangingConfigurations" devuelve verdadero
Porque la intención tiene límite de tamaño. Utilizo un objeto público estático para pasar el mapa de bits del servicio a la transmisión ...
public class ImageBox {
public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>();
}
pasar en mi servicio
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();
}
});
}
My 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
La respuesta aceptada se bloqueará cuando Bitmap
sea demasiado grande. Creo que es un límite de 1 MB . Se Bitmap
debe comprimir en un formato de archivo diferente, como un JPG representado por un ByteArray
, luego se puede pasar de forma segura a través de unIntent
.
La función está contenida en un hilo separado usando Kotlin Coroutines porque la Bitmap
compresión se encadena después de que Bitmap
se crea desde una url String
. La Bitmap
creación requiere un subproceso separado para evitar errores de aplicación que no responde (ANR) .
toBitmap()
hay una función de extensión de Kotlin que requiere que la biblioteca se agregue a las dependencias de la aplicación.Bitmap
a JPG ByteArray
después de que se haya creado.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
través de un Intent
.En esta muestra se pasa de un Fragmento a un Servicio . Es el mismo concepto si se comparte entre dos actividades .
Fragment.kt
ContextCompat.startForegroundService(
context!!,
Intent(context, AudioService::class.java).apply {
action = CONTENT_SELECTED_ACTION
putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
})
ByteArray
nuevo a 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()
}
}
Puede ser tarde pero puede ayudar. En el primer fragmento o actividad, declare una clase ... por ejemplo
@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;
}
Luego, en la segunda clase / fragmento, haga esto ...
Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;
Espero eso ayude.
Todas las soluciones anteriores no me funcionan, el envío de mapas de bits parceableByteArray
también genera errores android.os.TransactionTooLargeException: data parcel size
.
Solución
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)
comoIntent 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();
}
}
Puede crear una transferencia de mapa de bits. prueba esto....
En la primera clase:
1) Crear:
private static Bitmap bitmap_transfer;
2) Crear getter y setter
public static Bitmap getBitmap_transfer() {
return bitmap_transfer;
}
public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
bitmap_transfer = bitmap_transfer_param;
}
3) Establecer la imagen:
ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());
Luego, en la segunda clase:
ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));
En mi caso, la forma mencionada anteriormente no funcionó para mí. Cada vez que pongo el mapa de bits en la intención, la segunda actividad no comenzó. Lo mismo sucedió cuando pasé el mapa de bits como byte [].
Seguí este enlace y funcionó como un encanto y muy rápido:
package your.packagename
import android.graphics.Bitmap;
public class CommonResources {
public static Bitmap photoFinishBitmap = null;
}
en mi primera actividad:
Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);
y aquí está el onCreate () de mi segunda actividad:
@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
lugar de Constants.photoFinishBitmap
.
URI
oResourceID
del mapa de bits y no el propio mapa de bits. Pasar todo el mapa de bits requiere mucha memoria. Pasar la URL requiere muy poca memoria y permite que cada actividad cargue y escale el mapa de bits según lo necesite.