Domanda

Nella mia attività creo a Bitmap object e quindi devo avviarne un altro Activity, Come posso passare questo Bitmap oggetto dalla sottoattività (quella che verrà lanciata)?

È stato utile?

Soluzione

Bitmap implementa Parcelable, quindi si può sempre passare con l'intento:

Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);

e recuperarlo sull'altra estremità:

Intent intent = getIntent(); 
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");

Altri suggerimenti

In realtà, il superamento di un bitmap come Parcelable si tradurrà in un errore "JAVA BINDER GUASTO". Prova a passare il bitmap come matrice di byte e la costruzione per la visualizzazione dell'attività successiva.

Ho condiviso la mia soluzione qui:
come si fa a passare le immagini ( bitmap) tra le attività Android utilizzando fasci?

Passare la bitmap come parceable in bundle tra un'attività e l'altra non è una buona idea a causa della limitazione delle dimensioni di Parceable(1mb).È possibile archiviare la bitmap in un file nella memoria interna e recuperare la bitmap archiviata in diverse attività.Ecco del codice di esempio.

Per memorizzare bitmap in un file miaimmagine nella memoria interna:

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;
}

Quindi nell'attività successiva puoi decodificare questo file myImage in una bitmap utilizzando il seguente codice:

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

Nota Molti controlli per bitmap nulli e di ridimensionamento vengono omessi.

Se l'immagine è troppo grande e non è possibile salvare e caricarlo per l'archiviazione, si dovrebbe prendere in considerazione solo con un riferimento globale statico al bitmap (all'interno l'attività di ricezione), che sarà riportato a NULL in onDestory, solo se "isChangingConfigurations" restituisce true.

Perché Intent ha limite di dimensione. Io uso oggetto statico pubblico di fare passare bitmap dal servizio per trasmettere ....

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

passaggio nel mio servizio

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();
            }
        });
    }

Il mio 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);
            }
        }
    };

Comprimi e invia Bitmap

La risposta accettata si bloccherà quando il file Bitmap è troppo grande. Credo che sia un 1 MB limite.IL Bitmap deve essere compresso in un formato di file diverso come a JPG rappresentato da a ByteArray, quindi può essere passato in sicurezza tramite un file Intent.

Implementazione

La funzione è contenuta in un thread separato utilizzando Coroutine di Kotlin perché il Bitmap la compressione è concatenata dopo il Bitmap viene creato da un URL String.IL Bitmap la creazione richiede un thread separato per evitare L'applicazione non risponde (ANR) errori.

Concetti utilizzati

  • Coroutine di Kotlin Appunti.
  • IL Caricamento, contenuto, errore (LCE) il modello è utilizzato di seguito.Se sei interessato puoi saperne di più in questo discorso e questo video.
  • LiveData viene utilizzato per restituire i dati.Ho compilato il mio preferito LiveData risorsa dentro queste note.
  • In Passaggio 3, toBitmap() è un Funzione di estensione Kotlin richiedendo che la libreria venga aggiunta alle dipendenze dell'app.

Codice

1.Comprimere Bitmap A JPG ByteArray dopo che è stato creato.

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.Passa l'immagine come ByteArray tramite un Intent.

In questo campione è passato da a Frammento ad a Servizio.È lo stesso concetto se condiviso tra due Attività.

Frammento.kt

ContextCompat.startForegroundService(
    context!!,
    Intent(context, AudioService::class.java).apply {
        action = CONTENT_SELECTED_ACTION
        putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
    })

3.Convertire ByteArray tornare a Bitmap.

Utilis.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()
        }
    }

Potrebbe essere in ritardo, ma può aiutare. Sul primo frammento o attività fare dichiarare una classe ... per esempio

   @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;
}

Poi sulla seconda classe / frammento fare questo ..

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

Speranza che aiuta.

È possibile creare un trasferimento bitmap. provare questo ....

Nella prima classe:

1) Creazione:

private static Bitmap bitmap_transfer;

2) Creare getter e setter

public static Bitmap getBitmap_transfer() {
    return bitmap_transfer;
}

public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
    bitmap_transfer = bitmap_transfer_param;
}

3) Impostare l'immagine:

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

Poi, nella seconda classe:

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

Tutte le soluzioni di cui sopra non funziona per me, invio bitmap come parceableByteArray genera anche android.os.TransactionTooLargeException: data parcel size errore.

Soluzione

  1. salvata l'immagine bitmap nella memoria interna come:
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. e inviare in putExtra(String) come
Intent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
  1. e ricevilo in altre attività come:
if(getIntent() != null){
  try {
           src = BitmapFactory.decodeStream(openFileInput("myImage"));
       } catch (FileNotFoundException e) {
            e.printStackTrace();
      }

 }


Nel mio caso, il modo di cui sopra non ha funzionato per me. Ogni volta che ho messo la bitmap nell'intento, il 2 ° di attività non è stato avviato. Lo stesso è accaduto quando ho passato la bitmap come byte [].

Ho seguito questo link e ha funzionato come un fascino e molto veloce:

package your.packagename

import android.graphics.Bitmap;

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

nel mio primo acitiviy:

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

e qui è l'onCreate () della mia seconda attività:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Bitmap photo = Constants.photoFinishBitmap;
    if (photo != null) {
        mViewHolder.imageViewerImage.setImageDrawable(new BitmapDrawable(getResources(), photo));
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top