Jetpack পিকচার-ইন-পিকচার লাইব্রেরি ব্যবহার করা

পিকচার-ইন-পিকচার (PiP) Jetpack লাইব্রেরি Android অ্যাপ ডেভেলপারদের জন্য PiP কার্যকারিতা বাস্তবায়নের জন্য একটি সুবিন্যস্ত এবং শক্তিশালী সমাধান অফার করে, বিশেষ করে মিডিয়া প্লেব্যাক, ভিডিও কমিউনিকেশন এবং নেভিগেশন অ্যাপের জন্য। একটি ইউনিফায়েড API প্রদান করার মাধ্যমে, লাইব্রেরিটি বয়লারপ্লেট কোড, সাধারণ ইন-অ্যাপ বাগ দূর করতে এবং PiP ব্যবহারকারীর অভিজ্ঞতার সামগ্রিক কোয়ালিটি উন্নত করতে সাহায্য করে।

PiP Jetpack লাইব্রেরি, Android ইকোসিস্টেম জুড়ে বিভিন্ন মূল চ্যালেঞ্জ এবং অসঙ্গতির সমাধান করে বর্তমান PiP API-কে আরও উন্নত করে:

  • OS ফ্র্যাগমেন্টেশন: লাইব্রেরি অটোমেটিক বিভিন্ন Android ভার্সন জুড়ে PiP API কলের পার্থক্য ম্যানেজ করে, যেমন Android 12-এর আগে enterPictureInPictureMode এবং পরে isAutoEnterEnabled ব্যবহার করা, যাতে ডেভেলপারদের ভার্সনের পার্থক্য ম্যানেজ করতে না হয়।
  • ভুল PiP প্যারামিটার: এটি মিডিয়া প্লেব্যাকের সময় মসৃণ ও হাই-কোয়ালিটি অ্যানিমেশন তৈরি করার জন্য PiP প্যারামিটার, যেমন setSourceRectHint, সঠিকভাবে সেট করার জন্য একটি ইউনিফায়েড সমাধান প্রদান করে।
  • ইউনিফায়েড PiP স্টেট কলব্যাক: এটি onPictureInPictureModeChanged এবং onPictureInPictureUiStateChanged-কে একটি একক, ইউনিফায়েড কলব্যাক ইন্টারফেসে (PictureInPictureDelegate.OnPictureInPictureEventListener) একত্রিত করে যাতে স্টেট ও UI ম্যানেজমেন্ট সহজ হয়।
  • বয়লারপ্লেট কোড কমানো: লাইব্রেরিটি প্লেব্যাক কন্ট্রোল এবং ভিডিও কল অ্যাকশনের মতো সাধারণ ব্যবহারের ক্ষেত্রে RemoteActions-এর প্রি-ডিফাইন করা সেট অফার করে পুনরাবৃত্তিমূলক, বয়লারপ্লেট কোডের পরিমাণ কমায়।
  • ভবিষ্যতের জন্য প্রস্তুত করা: Jetpack লাইব্রেরির মাধ্যমে আরও PiP ফিচার প্রদান করা হয়, যা ব্যবহারকারীদের ন্যূনতম বা কোনও প্রচেষ্টা ছাড়াই অতিরিক্ত কার্যকারিতা অ্যাক্সেস করার অনুমতি দেয়।

মাইগ্রেশন ওয়ার্কফ্লো

অ্যাপের ব্যবহারের কেস ক্যাটেগরি এবং লিগ্যাসি PiP লজিক শনাক্ত করুন:

বিভাগ: ভিডিও প্লেব্যাক, নেভিগেশন বা ভিডিও কল।

শনাক্ত করার জন্য পুরনো PiP লজিক:

  • onUserLeaveHint
  • setAutoEnterEnabled
  • onPictureInPictureModeChanged
  • onPictureInPictureUiStateChanged
  • setPictureInPictureParams।

২. AndroidManifest কনফিগারেশন

নিশ্চিত করুন যে PiP-তে প্রবেশ করা অ্যাক্টিভিটি AndroidManifest.xml-এ প্রয়োজনীয় configChanges-এর সাথে সাপোর্ট ঘোষণা করে যাতে অপ্রয়োজনীয় রিস্টার্ট আটকানো যায়:

<activity
android:name="VideoActivity" android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation">
</activity>

৩. এনভায়রনমেন্ট সেট-আপ

build.gradle-এ প্রয়োজনীয় ডিপেন্ডেন্সি যোগ করুন:

dependencies {
implementation("androidx.core:core:1.18.0")
implementation("androidx.activity:activity:1.13.0")
implementation("androidx.core:core-pip:1.0.0-alpha02") }

ডিপেন্ডেন্সির জন্য লেটেস্ট AndroidX লাইব্রেরি ব্যবহার করুন এবং সেই তথ্যের জন্য রিলিজ পৃষ্ঠা দেখুন।

৪. টেমপ্লেট বেছে নেওয়া ও শুরু করা

অ্যাপের ব্যবহারের ক্ষেত্রে সবচেয়ে উপযুক্ত ইমপ্লিমেন্টেশন টেমপ্লেট বেছে নিন:

  • নেভিগেশন ও ভিডিও কল: BasicPictureInPicture; সাধারণত সিমলেস রিসাইজ কাজ করে না এবং সোর্স রেকট হিন্টের প্রয়োজন হয় না।
  • ভিডিও প্লেব্যাক: VideoPlaybackPictureInPicture; সোর্স রেক্ট হিন্টের জন্য প্লেয়ার ভিউ বাউন্ড অটোমেটিক ট্র্যাক করে এবং ডিফল্ট হিসেবে নির্বিঘ্নে সাইজ পরিবর্তন করার সুবিধা চালু করে।

Jetpack লাইব্রেরি গ্রহণ করতে, আপনার বর্তমান কাস্টম PiP প্রয়োগের পরিবর্তে Jetpack লাইব্রেরি API ব্যবহার করুন। অ্যাপের বর্তমান ইমপ্লিমেন্টেশনের উপর নির্ভর করে এটি গ্রহণ করার জটিলতা ও খরচ পরিবর্তিত হবে।

নিচের বিভাগগুলিতে PiP-এর কিছু সাধারণ ব্যবহারের উদাহরণ এবং প্রয়োজনীয় প্রয়োগের ধাপগুলি বর্ণনা করা হয়েছে:

অ্যাপটি লাইব্রেরিকে নেভিগেশনের অ্যাক্টিভ বা ইনঅ্যাক্টিভ অবস্থা সম্পর্কে জানায় এবং অ্যাস্পেক্ট রেশিও সেট করে। বাকি কাজ Jetpack লাইব্রেরি করে নেয়।

প্রধান পার্থক্য:

  1. অ্যাপের দিকে অটো-এন্টার এবং লিগ্যাসি-এন্টার আলাদা করার দরকার নেই।
  2. কনসোলিডেট করা কলব্যাক ইন্টারফেস।
  3. পুরনো ভার্সনের সাথে মানানসই হওয়ার জন্য নতুন PictureInPictureParams বিল্ডার।

ভিডিও কল করুন

অ্যাপটি লাইব্রেরিকে কলের অ্যাক্টিভ বা ইনঅ্যাক্টিভ স্ট্যাটাস সম্পর্কে জানায় এবং অ্যাস্পেক্ট রেশিও সেট করে।

প্রধান পার্থক্য:

  1. অ্যাপের দিকে অটো-এন্টার এবং লিগ্যাসি-এন্টার আলাদা করার দরকার নেই।
  2. কনসোলিডেট করা কলব্যাক ইন্টারফেস।
  3. পুরনো ভার্সনের সাথে মানানসই হওয়ার জন্য নতুন PictureInPictureParams বিল্ডার।
  4. ভিডিও কলের জন্য স্ট্যান্ডার্ডাইজড অ্যাকশন আইকন।

৫. কোড মাইগ্রেশন

  • এন্ট্রি লজিক: API-নির্দিষ্ট লজিক যেমন Android 12 এবং তার পরবর্তী যেকোনও ভার্সনের জন্য setAutoEnterEnabled অথবা Android 11 এবং তার পূর্ববর্তী যেকোনও ভার্সনের জন্য onUserLeaveHint-এর পরিবর্তে setEnabled ব্যবহার করুন। PiP-এর উপযুক্ততার স্ট্যাটাস পরিবর্তন হলেই এটি ট্রিগার করুন।
  • কলব্যাক: onPictureInPictureModeChanged (লেআউট টগল করা) এবং onPictureInPictureUiStateChanged (অ্যানিমেশন/স্টেট) একত্রিত করে একটি ইউনিফায়েড ইভেন্ট-ভিত্তিক কলব্যাক onPictureInPictureEvent-এ পরিণত করুন।
  • অ্যাকশন ও প্যারামিটার: টেমপ্লেট ইনস্ট্যান্সের প্যারামিটার যখনই পরিবর্তন হবে, তখনই setActions এবং setAspectRatio ব্যবহার করে তা আপডেট করুন।

রেফারেন্স ইমপ্লিমেন্টেশন প্যাটার্ন

প্রয়োগের উদাহরণ।

নেভিগেশন ও ভিডিও কল

class NavOrVideoCallJpipActivity : ComponentActivity(), PictureInPictureDelegate.OnPictureInPictureEventListener {
    private lateinit var pictureInPictureImpl: BasicPictureInPicture
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        pictureInPictureImpl = BasicPictureInPicture(this)
        // BasicPictureInPicture is ideal for Navigation and Video call use cases.
        pictureInPictureImpl.addOnPictureInPictureEventListener(
            ContextCompat.getMainExecutor(this),
            this
        )
        setContent {
        }
    }
    override fun onPictureInPictureEvent(
        event: PictureInPictureDelegate.Event,
        config: Configuration?
    ) {
        when (event) {
            PictureInPictureDelegate.Event.ENTERED -> { /* Toggle to PiP layout */ }
            PictureInPictureDelegate.Event.EXITED -> { /* Toggle to Full-screen layout */ }
            PictureInPictureDelegate.Event.STASHED -> { /* Optional: PiP is stashed */ }
            PictureInPictureDelegate.Event.UNSTASHED -> { /* Optional: PiP is unstashed */ }
        }
    }
}

ভিডিও প্লেব্যাক

class VideoPlaybackJpipActivity : ComponentActivity(), PictureInPictureDelegate.OnPictureInPictureEventListener {
    private lateinit var pictureInPictureImpl: VideoPlaybackPictureInPicture
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        pictureInPictureImpl = VideoPlaybackPictureInPicture(this)
        pictureInPictureImpl.addOnPictureInPictureEventListener(
            ContextCompat.getMainExecutor(this),
            this
        )
        setContent {
            ContentScreen(pictureInPictureImpl)
        }
    }
    override fun onPictureInPictureEvent(
        event: PictureInPictureDelegate.Event,
        config: Configuration?
    ) {
        when (event) {
            PictureInPictureDelegate.Event.ENTER_ANIMATION_START -> { /* Hide overlays */ }
            PictureInPictureDelegate.Event.ENTER_ANIMATION_END -> { /* Animation finished */ }
            PictureInPictureDelegate.Event.ENTERED -> { /* Switch to PiP layout */ }
            PictureInPictureDelegate.Event.STASHED -> { /* PiP stashed */ }
            PictureInPictureDelegate.Event.UNSTASHED -> { /* PiP unstashed */ }
            PictureInPictureDelegate.Event.EXITED -> { /* Return to full-screen */ }
        }
    }

    @Composable
    fun ContentScreen(pipController: VideoPlaybackPictureInPicture) {
        DisposableEffect(pipController) {
            onDispose {
                pipController.close()
            }
        }
    }
}