আমি কীভাবে একটি বিটম্যাপ অবজেক্টকে অন্য ক্রিয়াকলাপ থেকে পাস করতে পারি


145

আমার ক্রিয়াকলাপে, আমি একটি Bitmapবস্তু তৈরি করি এবং তারপরে আমার আর একটি চালু করতে হবেActivity করতে হবে, আমি কীভাবে Bitmapসাব-ক্রিয়াকলাপটি (যেটি চালু করা হচ্ছে) থেকে এই বস্তুটি পাস করতে পারি ?

উত্তর:


297

Bitmapপ্রয়োগ Parcelable, যাতে আপনি সর্বদা এটি অভিপ্রায় সহ পাস করতে পারেন:

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

এবং অন্য প্রান্তে এটি পুনরুদ্ধার করুন:

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

84
বিটম্যাপ ফাইল বা একটি সম্পদ হিসেবে বিদ্যমান, তাহলে এটির সবসময় পাস করাই ভালো URIবা ResourceIDবিটম্যাপ বিটম্যাপ নিজেই এবং। পুরো বিটম্যাপটি পাস করার জন্য প্রচুর স্মৃতি দরকার। ইউআরএল পাস করার জন্য খুব অল্প স্মৃতি দরকার এবং প্রতিটি ক্রিয়াকলাপটি যেমন প্রয়োজন তেমন বিটম্যাপটি লোড করতে এবং স্কেল করতে দেয়।
স্লেটন

3
আমার জন্য কাজ করে না, কিন্তু এই কোন একটি করুন: stackoverflow.com/questions/11010386/...
হুসেম

1
@ স্লেটন কীভাবে আমরা ইউআরআই / রিসোর্সআইডি হিসাবে চিত্রগুলি পাস করব? উদাহরণ? ধন্যবাদ!
11:30

এই জাতীয় অতিরিক্ত বিটম্যাপ লাগানো সর্বোত্তম অনুশীলন নয়, যদি বিটম্যাপ অবজেক্টের আকার বড় হয় তবে আপনি "java.lang.SecurityException" কলার অ্যান্ড্রয়েড.এপ. অ্যাপ্লিকেশনথ্রেডপ্রক্সির জন্য অ্যাপ্লিকেশন খুঁজে পেতে অক্ষম ...... "। প্রস্তাবিত উপায়টি @ স্লেটন বলেছে যে, আপনাকে বাহ্যিক স্টোরেজে বিটম্যাপ সংরক্ষণ করতে হবে এবং কেবল ইউআরআই পাস করতে হবে।
AITAALI_ABDERRAHMANE

1
বিটম্যাপটি সর্বোচ্চ আকারটি কী হতে পারে?
আতিফসায়িংস

24

প্রকৃতপক্ষে, পার্সলেবল হিসাবে একটি বিটম্যাপটি পাস করার ফলে "জাভা বাইন্ডার ব্যর্থতা" ত্রুটি হবে। বাইট অ্যারে হিসাবে বিটম্যাপটি পাস করার চেষ্টা করুন এবং পরবর্তী ক্রিয়াকলাপে এটি প্রদর্শনের জন্য তৈরি করুন।

আমি এখানে আমার সমাধানটি ভাগ করেছি: আপনি
কীভাবে বান্ডিলগুলি ব্যবহার করে অ্যান্ড্রয়েড ক্রিয়াকলাপগুলির মধ্যে চিত্রগুলি (বিটম্যাপস) পাস করবেন?


16

পার্সেবল (1 মিমি) আকারের সীমাবদ্ধতার কারণে ক্রিয়াকলাপের মধ্যে বান্ডলে পার্টেবল হিসাবে বিটম্যাপটি উত্তোলন করা ভাল ধারণা নয়। আপনি অভ্যন্তরীণ স্টোরেজে কোনও ফাইলে বিটম্যাপ সংরক্ষণ করতে পারেন এবং বেশ কয়েকটি ক্রিয়াকলাপে সঞ্চিত বিটম্যাপটি পুনরুদ্ধার করতে পারেন। এখানে কিছু নমুনা কোড।

অভ্যন্তরীণ স্টোরেজে আমার আইমেজ ফাইলটিতে বিটম্যাপ সংরক্ষণ করতে:

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
হকক্লিক

4

চিত্রটি যদি খুব বড় হয় এবং আপনি এটি স্টোরেজে সঞ্চয় করতে এবং লোড করতে না পারেন, তবে আপনাকে কেবল বিটম্যাপের (প্রাপ্ত ক্রিয়াকলাপের অভ্যন্তরে) একটি বিশ্বব্যাপী স্ট্যাটিক রেফারেন্স ব্যবহার করা উচিত, যা কেবলমাত্র "isChangingConfigurations" হলেই onDestory এ বাতিল হয়ে যাবে reset সত্য ফিরে।


3

কারণ ইন্টেন্টের আকারের সীমা রয়েছে। আমি পরিষেবা থেকে সম্প্রচারে বিটম্যাপ পাস করতে সর্বজনীন স্ট্যাটিক অবজেক্ট ব্যবহার করি ....

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

2

কমপ্রেস এবং প্রেরণ করুন Bitmap

গৃহীত উত্তর ক্র্যাশ হয়ে যাবে যখন Bitmapখুব বড় হবে। আমি বিশ্বাস করি এটি 1MB সীমা। Bitmapযেমন একটি হিসাবে একটি আলাদা ফাইল বিন্যাসে সংকুচিত করা আবশ্যক JPG, একটি দ্বারা প্রতিনিধিত্ব ByteArray, তাহলে এটি নিরাপদে কোনও মাধ্যমে প্রেরণ করা সম্ভবIntent

বাস্তবায়ন

ফাংশনটি কোটলিন Coroutines ব্যবহার করে একটি পৃথক থ্রেডে অন্তর্ভুক্ত কারণ একটি ইউআরএল থেকে তৈরি Bitmapহওয়ার পরে সংকোচনের শৃঙ্খলাবদ্ধ । সৃষ্টি এড়াতে অনুক্রমে একটি পৃথক থ্রেডে প্রয়োজন APPLICATION সাড়া দিচ্ছে না (ANR- এর) ত্রুটি।BitmapStringBitmap

ব্যবহৃত ধারণা

  • কোটলিন Coroutines নোট
  • লোড হচ্ছে, সামগ্রী, ত্রুটি (LCE) প্যাটার্ন নিচের ব্যবহার করা হয়। আগ্রহী হলে আপনি এই আলোচনা এবং ভিডিওতে এটি সম্পর্কে আরও শিখতে পারেন ।
  • লাইভডেটা ডেটা ফেরত দেওয়ার জন্য ব্যবহৃত হয়। আমি এই নোটগুলিতে আমার প্রিয় লাইভ ডেটা সংস্থানটি সংকলন করেছি ।
  • ইন ধাপ 3 , toBitmap()একটি হল Kotlin এক্সটেনশন ফাংশন লাইব্রেরির প্রয়োজন অ্যাপ্লিকেশন নির্ভরতা যোগ করা হবে।

কোড

1. কম্প্রেস Bitmapকরার JPG, 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}")
            }
        }
    })
}

2. ByteArrayএকটি হিসাবে হিসাবে ছবি পাস Intent

এই নমুনায় এটি একটি টুকরা থেকে একটি পরিষেবাতে পাস হয়েছে । দুটি ক্রিয়াকলাপের মধ্যে ভাগ করা হলে এটি একই ধারণা ।

Fragment.kt

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

3. রূপান্তর 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()
        }
    }

1

এটি দেরিতে হতে পারে তবে সাহায্য করতে পারে। প্রথম খণ্ড বা ক্রিয়াকলাপে কোনও শ্রেণি ঘোষণা করুন ... উদাহরণস্বরূপ

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

আশা করি এটা সাহায্য করবে.


1

উপরের সমস্ত সমাধান আমার পক্ষে কাজ করে না, বিটম্যাপ প্রেরণও parceableByteArrayত্রুটি উত্পন্ন করে android.os.TransactionTooLargeException: data parcel size

সমাধান

  1. অভ্যন্তরীণ স্টোরেজে বিটম্যাপটি সংরক্ষণ করা হয়েছে:
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. এবং putExtra(String)হিসাবে প্রেরণ
Intent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
  1. এবং অন্যান্য ক্রিয়াকলাপে এটি পান যেমন:
if(getIntent() != null){
  try {
           src = BitmapFactory.decodeStream(openFileInput("myImage"));
       } catch (FileNotFoundException e) {
            e.printStackTrace();
      }

 }


0

আপনি একটি বিটম্যাপ স্থানান্তর তৈরি করতে পারেন। এটা চেষ্টা কর....

প্রথম শ্রেণিতে:

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

-2

আমার ক্ষেত্রে, উপরে উল্লিখিত পদ্ধতিটি আমার পক্ষে কার্যকর হয়নি। আমি যতবার বিটম্যাপটি অভিপ্রায় রেখেছি, ততবার দ্বিতীয় ক্রিয়াকলাপটি শুরু হয়নি। আমি যখন বাইট হিসাবে বিটম্যাপটি পাস করেছি তখন একই ঘটনা ঘটে []।

আমি এই লিঙ্কটি অনুসরণ করেছি এবং এটি একটি আকর্ষণীয় এবং খুব দ্রুত কাজ করেছে:

package your.packagename

import android.graphics.Bitmap;

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

আমার 1 ম অ্যাকটিভিয়ায়:

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
নাথান হাটন

খারাপ অনুশীলন। পুরো প্রক্রিয়াটি পুনরায় বিনোদনের সময় অ্যাক্টিভিটি ক্লাসে স্ট্যাটিক ফিল্ডের সাথে কী ঘটবে (উদাহরণস্বরূপ, রানটাইমে অ্যাপের জন্য অনুমতি পরিবর্তন করার কারণে)? উত্তরটি এনপিই।
আলেকজান্ডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.