Dans mon activité, je crée un objet Bitmap
puis je dois lancer un autre Activity
, Comment puis-je transmettre cet objet Bitmap
de la sous-activité (celle qui va être lancée)?
Bitmap
implémente Parcelable
, vous pouvez donc toujours le transmettre avec l'intention:
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
et le récupérer à l'autre bout:
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
En fait, le fait de passer un bitmap en tant que parcelle entraînera une erreur "Java BINDER FAILURE". Essayez de passer le bitmap sous forme de tableau d'octets et de le construire pour l'afficher dans l'activité suivante.
J'ai partagé ma solution ici:
Comment passez-vous les images (bitmaps) entre les activités Android à l'aide de bundles?
Passer des images bitmap comme pouvant être groupées entre activités n’est pas une bonne idée en raison de la limitation de la taille de cette option. Vous pouvez stocker le bitmap dans un fichier de la mémoire interne et récupérer le bitmap stocké dans plusieurs activités. Voici un exemple de code.
Pour stocker une image bitmap dans un fichier myImage dans la mémoire de stockage interne:
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;
}
Ensuite, dans l'activité suivante, vous pouvez décoder ce fichier myImage en une bitmap à l'aide du code suivant:
//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));
Remarque De nombreuses vérifications de null et de mise à l'échelle des images bitmap sont omises.
Si l'image est trop grande et que vous ne pouvez pas l'enregistrer et la charger dans le stockage, vous devriez envisager d'utiliser simplement une référence statique globale au bitmap (dans l'activité de réception), qui sera réinitialisée à null sur onDestory, uniquement si "isChangingConfigurations" retourne vrai.
Parce que Intent a une taille limite . J'utilise un objet statique public pour faire passer bitmap du service à la diffusion ....
public class ImageBox {
public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>();
}
passer à mon service
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();
}
});
}
Mon 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 réponse acceptée plantera lorsque la Bitmap
est trop grande. Je crois que c'est un 1MB limite. La Bitmap
doit être compressée dans un format de fichier différent, tel qu'un JPG représenté par un ByteArray
, puis il peut être passé en toute sécurité via un Intent
.
La fonction est contenue dans un fil séparé utilisant Kotlin Coroutines car la compression Bitmap
est chaînée après la création de la Bitmap
url String
. La création de Bitmap
nécessite un thread distinct afin d'éviter les erreurs de l'application sans réponse (ANR) .
toBitmap()
est un fonction d'extension Kotlin nécessitant l'ajout de cette bibliothèque aux dépendances de l'application.Bitmap
en JPGByteArray
après sa création.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
via un Intent
.Dans cet exemple, il est passé d'un fragment à un service . C'est le même concept si partagé entre deux activités .
Fragment.kt
ContextCompat.startForegroundService(
context!!,
Intent(context, AudioService::class.Java).apply {
action = CONTENT_SELECTED_ACTION
putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
})
ByteArray
en 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()
}
}
Toutes les solutions ci-dessus ne fonctionnent pas pour moi. L'envoi d'un bitmap en tant que parceableByteArray
génère également l'erreur Android.os.TransactionTooLargeException: data parcel size
.
Solution
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)
en tant queIntent 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();
}
}
Vous pouvez créer un transfert bitmap. essaye ça....
En première classe:
1) Créer:
private static Bitmap bitmap_transfer;
2) Créer un getter et un setter
public static Bitmap getBitmap_transfer() {
return bitmap_transfer;
}
public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
bitmap_transfer = bitmap_transfer_param;
}
3) Définissez l'image:
ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());
Ensuite, en deuxième classe:
ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));
Cela peut être tard mais peut aider . Sur le premier fragment ou activité, déclarez une classe ... par exemple
@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;
}
Ensuite, sur la seconde classe/fragment, faites ceci ..
Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;
J'espère que ça aide.