Question

Dans mon activité, je crée un Bitmap objet et ensuite je dois en lancer un autre Activity, Comment puis-je passer ça Bitmap objet de la sous-activité (celle qui va être lancée) ?

Était-ce utile?

La solution

Bitmap implémente Parcelable, donc vous pouvez toujours passer 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");

Autres conseils

En fait, le passage d'un bitmap en tant que Parcelable se traduira par une erreur « JAVA BINDER FAILURE ». Essayez le passage du bitmap en tant que tableau d'octets et la construction pour l'affichage à l'activité suivante.

Je partageais ici ma solution:
comment passez-vous des images ( bitmaps) entre les activités Android à l'aide des paquets

Passsing bitmap parceable en bundle entre l'activité n'est pas une bonne idée en raison de la limitation de la taille des Parceable (1MB). Vous pouvez stocker le bitmap dans un fichier dans la mémoire interne et récupérer le bitmap stocké dans plusieurs activités. Voici quelques exemples de code.

Pour stocker dans un fichier bitmap myImage dans le 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 à un bitmap en utilisant le code suivant:

//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));

Remarque Beaucoup de vérification de bitmap NULL et mise à l'échelle de ommited est.

Si l'image est trop grande et vous ne pouvez pas enregistrer et charger sur le stockage, vous devriez considérer simplement en utilisant une référence statique globale au bitmap (dans l'activité de réception), qui sera remis à null sur onDestory, seulement si "isChangingConfigurations" retourne vrai.

Parce que Intent a la limite de taille. J'utilise objet statique public de le faire bitmap passe du service à diffuser ....

public class ImageBox {
    public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>(); 
}

passe dans 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);
            }
        }
    };

Compresser et envoyer Bitmap

La réponse acceptée plantera lorsque le Bitmap est trop grand. je crois que c'est un 1 Mo limite.Le Bitmap doit être compressé dans un format de fichier différent tel qu'un JPG représenté par un ByteArray, il peut alors être transmis en toute sécurité via un Intent.

Mise en œuvre

La fonction est contenue dans un thread séparé utilisant Coroutines Kotlin parce que le Bitmap la compression est enchaînée après le Bitmap est créé à partir d'une URL String.Le Bitmap la création nécessite un thread séparé afin d'éviter L'application ne répond pas (ANR) les erreurs.

Concepts utilisés

  • Coroutines Kotlin Remarques.
  • Le Chargement, contenu, erreur (LCE) le modèle est utilisé ci-dessous.Si vous êtes intéressé, vous pouvez en savoir plus sur cette conférence et cette vidéo.
  • Données en direct est utilisé pour renvoyer les données.J'ai compilé mes favoris Données en direct ressource dans ces notes.
  • Dans Étape 3, toBitmap() est un Fonction d'extension Kotlin exigeant que cette bibliothèque soit ajoutée aux dépendances de l'application.

Code

1.Compresse Bitmap à JPG ByteArray après sa création.

Dépôt.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.Passer l'image comme ByteArray via un Intent.

Dans cet exemple, il est transmis d'un Fragment à un Service.C'est le même concept s'il est 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)
    })

3.Convertir ByteArray retour à 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()
        }
    }

Il est peut-être en retard, mais peut aider. Sur le premier fragment ou une activité faire déclarer 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 deuxième classe / fragment faire ..

Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;

it helps.

Vous pouvez créer un transfert bitmap. essayer ....

Dans la première classe:

1) Créer:

private static Bitmap bitmap_transfer;

2) Créer getter et 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éfinir l'image:

ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());

Ensuite, dans la deuxième classe:

ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));

Toutes les solutions ci-dessus ne fonctionne pas pour moi, Envoi bitmap parceableByteArray génère également android.os.TransactionTooLargeException: data parcel size d'erreur.

Solution

  1. Enregistré le bitmap dans la mémoire interne comme suit:
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;
    }
  1. et envoyer putExtra(String) comme
Intent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
  1. et le recevoir dans d'autres activités comme:
if(getIntent() != null){
  try {
           src = BitmapFactory.decodeStream(openFileInput("myImage"));
       } catch (FileNotFoundException e) {
            e.printStackTrace();
      }

 }


Dans mon cas, la manière mentionnée ci-dessus n'a pas fonctionné pour moi. Chaque fois que je mets le bitmap dans l'intention, la 2e activité n'a pas démarré. La même chose est arrivée quand je suis passé le bitmap comme octet [].

Je suivais cette et cela a fonctionné comme un charme et très rapide:

package your.packagename

import android.graphics.Bitmap;

public class CommonResources { 
      public static Bitmap photoFinishBitmap = null;
}

dans mon 1er acitiviy:

Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);

et voici le onCreate () de mon 2ème activité:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Bitmap photo = Constants.photoFinishBitmap;
    if (photo != null) {
        mViewHolder.imageViewerImage.setImageDrawable(new BitmapDrawable(getResources(), photo));
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top