जवाबों:
Bitmap
औजार Parcelable
, ताकि आप हमेशा इसे इरादे से पास कर सकें:
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
और इसे दूसरे छोर पर पुनः प्राप्त करें:
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
वास्तव में, एक बिटमैप को पार्सल के रूप में पारित करने के परिणामस्वरूप "JAVA BINDER FAILURE" त्रुटि होगी। बिटमैप को बाइट सरणी के रूप में पास करने की कोशिश करें और इसे अगली गतिविधि में प्रदर्शन के लिए बनाएं।
मैंने अपना समाधान यहां साझा किया:
आप बंडलों का उपयोग करके एंड्रॉइड गतिविधियों के बीच छवियां (बिटमैप) कैसे पास करते हैं?
गतिविधि के बीच बंडल में पैरेसेबल के रूप में बिटमैप को पास करना पारसेबल (1mb) के आकार की सीमा के कारण एक अच्छा विचार नहीं है। आप किसी फ़ाइल में बिटमैप को आंतरिक संग्रहण में संग्रहीत कर सकते हैं और संग्रहीत बिटमैप को कई गतिविधियों में पुनर्प्राप्त कर सकते हैं। यहाँ कुछ नमूना कोड है।
आंतरिक संग्रहण में myImage फ़ाइल में बिटमैप संग्रहीत करने के लिए :
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;
}
फिर अगली गतिविधि में आप निम्न कोड का उपयोग करके बिटमैप को इस फ़ाइल को डिकोड कर सकते हैं:
//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));
नोट बिटमैप के लिए अशक्त और स्केलिंग के लिए बहुत सारी जाँच की जाती है।
openFileOutput
।
यदि छवि बहुत बड़ी है और आप इसे सहेज नहीं सकते हैं और इसे स्टोरेज में लोड नहीं कर सकते हैं, तो आपको बिटमैप पर एक वैश्विक स्थिर संदर्भ (प्राप्त गतिविधि के अंदर) का उपयोग करने पर विचार करना चाहिए, जो कि onDestory पर शून्य करने के लिए रीसेट हो जाएगा, केवल तभी जब "ChancConfigurations " सच लौटाता है।
क्योंकि आशय की आकार सीमा है। मैं सार्वजनिक स्थैतिक वस्तु का उपयोग सेवा से प्रसारण तक बिटमैप करने के लिए करता हूं ...।
public class ImageBox {
public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>();
}
मेरी सेवा में पास
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();
}
});
}
माई ब्रॉडकास्टसीवर
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
स्वीकृत उत्तर Bitmap
बहुत बड़ा होने पर क्रैश हो जाएगा । मेरा मानना है कि यह 1MB की सीमा है। Bitmap
एक अलग फ़ाइल स्वरूप के रूप में एक में संकुचित किया जाना चाहिए जेपीजी एक द्वारा प्रतिनिधित्वByteArray
है, तो यह सुरक्षित रूप से एक के माध्यम से पारित किया जा सकता Intent
।
कोटलिन कॉरटाइन्स का उपयोग करके फ़ंक्शन को एक अलग थ्रेड में समाहित किया गया है क्योंकि एक यूआरएल से निर्मित Bitmap
होने के बाद संपीड़न जंजीर Bitmap
है String
। Bitmap
निर्माण से बचने के क्रम में एक अलग थ्रेड की आवश्यकता है आवेदन प्रतिसाद नहीं (ANR) त्रुटियों।
toBitmap()
एक है Kotlin विस्तार समारोह है कि पुस्तकालय की आवश्यकता होती है अनुप्रयोग निर्भरता के लिए जोड़ा जा करने के लिए।Bitmap
करें । ByteArray
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
एक के माध्यम से Intent
।इस नमूने में यह एक फ्रैगमेंट से एक सेवा के लिए पारित किया गया है । दो गतिविधियों के बीच साझा किए जाने पर यह एक ही अवधारणा है ।
Fragment.kt
ContextCompat.startForegroundService(
context!!,
Intent(context, AudioService::class.java).apply {
action = CONTENT_SELECTED_ACTION
putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
})
ByteArray
वापस कन्वर्ट 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()
}
}
यह देर हो सकती है लेकिन मदद कर सकती है। पहले टुकड़े या गतिविधि पर एक वर्ग घोषित करते हैं ... उदाहरण के लिए
@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;
}
फिर दूसरी कक्षा / खंड पर यह करें ।।
Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;
आशा करता हूँ की ये काम करेगा।
उपरोक्त सभी समाधान मेरे लिए काम नहीं करते हैं, बिटमैप भेजना parceableByteArray
भी त्रुटि उत्पन्न करता हैandroid.os.TransactionTooLargeException: data parcel size
।
उपाय
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)
के रूप मेंIntent 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();
}
}
आप एक बिटमैप स्थानांतरण बना सकते हैं। इसे इस्तेमाल करे....
पहली कक्षा में:
1) बनाएं:
private static Bitmap bitmap_transfer;
2) गेट्टर और सेटर बनाएं
public static Bitmap getBitmap_transfer() {
return bitmap_transfer;
}
public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
bitmap_transfer = bitmap_transfer_param;
}
3) छवि सेट करें:
ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());
फिर, दूसरी कक्षा में:
ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));
मेरे मामले में, ऊपर बताए गए तरीके ने मेरे लिए काम नहीं किया। हर बार जब मैंने बिटमैप को इरादे में रखा, तो दूसरी गतिविधि शुरू नहीं हुई। वही हुआ जब मैंने बिटमैप को बाइट के रूप में पारित किया []।
मैंने इस लिंक का अनुसरण किया और इसने बहुत ही तेजी से काम किया और बहुत तेजी से:
package your.packagename
import android.graphics.Bitmap;
public class CommonResources {
public static Bitmap photoFinishBitmap = null;
}
मेरी पहली एसिटिविय में:
Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);
और यहाँ मेरी दूसरी गतिविधि का हिस्सा है ():
@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
इसके बजाय उपयोग करना चाहिए था Constants.photoFinishBitmap
।
URI
याResourceID
बिटमैप बिटमैप ही की और नहीं। पूरे बिटमैप को पास करने के लिए बहुत अधिक मेमोरी की आवश्यकता होती है। URL पास करने के लिए बहुत कम मेमोरी की आवश्यकता होती है और प्रत्येक गतिविधि को बिटमैप को लोड करने और स्केल करने की अनुमति देता है, क्योंकि उन्हें इसकी आवश्यकता होती है।