ফোল্ডেবল ডিসপ্লে মোড সমর্থন করে

ভাঁজযোগ্য ডিভাইসগুলি অনন্য দেখার অভিজ্ঞতা দেয়। রিয়ার ডিসপ্লে মোড এবং ডুয়াল-স্ক্রিন মোড আপনাকে ভাঁজযোগ্য ডিভাইসগুলির জন্য বিশেষ ডিসপ্লে বৈশিষ্ট্য তৈরি করতে সক্ষম করে যেমন রিয়ার-ক্যামেরা সেলফি প্রিভিউ এবং অভ্যন্তরীণ এবং বাইরের স্ক্রিনে একই সাথে কিন্তু ভিন্ন ডিসপ্লে।

রিয়ার ডিসপ্লে মোড

সাধারণত যখন একটি ভাঁজযোগ্য ডিভাইস খোলা হয়, তখন শুধুমাত্র ভিতরের পর্দা সক্রিয় থাকে। রিয়ার ডিসপ্লে মোড আপনাকে একটি ক্রিয়াকলাপকে একটি ভাঁজযোগ্য ডিভাইসের বাইরের স্ক্রিনে সরাতে দেয়, যা সাধারণত ডিভাইসটি খোলার সময় ব্যবহারকারীর কাছ থেকে দূরে থাকে। অভ্যন্তরীণ প্রদর্শন স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যায়।

একটি অভিনব অ্যাপ্লিকেশন হল বাইরের স্ক্রিনে ক্যামেরা প্রিভিউ প্রদর্শন করা, যাতে ব্যবহারকারীরা পেছনের ক্যামেরা দিয়ে সেলফি তুলতে পারে, যা সাধারণত সামনের ক্যামেরার চেয়ে অনেক ভালো ছবি তোলার পারফরম্যান্স প্রদান করে।

রিয়ার ডিসপ্লে মোড সক্রিয় করতে, ব্যবহারকারীরা অ্যাপটিকে স্ক্রিন পরিবর্তন করার অনুমতি দেওয়ার জন্য একটি ডায়ালগে সাড়া দেয়, উদাহরণস্বরূপ:

চিত্র 1. সিস্টেম ডায়ালগ রিয়ার ডিসপ্লে মোড শুরু করার অনুমতি দেয়।

সিস্টেম ডায়ালগ তৈরি করে, তাই আপনার পক্ষ থেকে কোন উন্নয়নের প্রয়োজন নেই। ডিভাইসের অবস্থার উপর নির্ভর করে বিভিন্ন ডায়ালগ উপস্থিত হয়; উদাহরণস্বরূপ, ডিভাইসটি বন্ধ থাকলে সিস্টেমটি ব্যবহারকারীদের ডিভাইসটি খোলার নির্দেশ দেয়। আপনি ডায়ালগটি কাস্টমাইজ করতে পারবেন না এবং এটি বিভিন্ন OEM থেকে ডিভাইসে পরিবর্তিত হতে পারে।

আপনি পিক্সেল ফোল্ড ক্যামেরা অ্যাপের মাধ্যমে রিয়ার ডিসপ্লে মোড ব্যবহার করে দেখতে পারেন। কোডল্যাবে একটি নমুনা বাস্তবায়ন দেখুন Jetpack WindowManager-এর সাহায্যে ফোল্ডেবল ডিভাইসে আপনার ক্যামেরা অ্যাপ অপ্টিমাইজ করুন

ডুয়াল-স্ক্রিন মোড

ডুয়াল-স্ক্রিন মোড আপনাকে একই সময়ে ফোল্ডেবলের উভয় ডিসপ্লেতে সামগ্রী প্রদর্শন করতে দেয়। ডুয়াল-স্ক্রিন মোড Android 14 (API লেভেল 34) বা উচ্চতর চলমান Pixel Fold-এ উপলব্ধ।

একটি উদাহরণ ব্যবহারের ক্ষেত্রে ডুয়াল-স্ক্রিন ইন্টারপ্রেটার।

চিত্র 2. ডুয়াল-স্ক্রিন ইন্টারপ্রেটার সামনে এবং পিছনের ডিসপ্লেতে বিভিন্ন বিষয়বস্তু দেখাচ্ছে।

প্রোগ্রামগতভাবে মোড সক্রিয় করুন

আপনি লাইব্রেরি সংস্করণ 1.2.0-beta03 থেকে শুরু করে Jetpack WindowManager API-এর মাধ্যমে রিয়ার ডিসপ্লে মোড এবং ডুয়াল-স্ক্রিন মোড অ্যাক্সেস করতে পারেন।

আপনার অ্যাপের মডিউল build.gradle ফাইলে WindowManager নির্ভরতা যোগ করুন:

গ্রোভি

dependencies {
    implementation "androidx.window:window:1.2.0-beta03"
}

কোটলিন

dependencies {
    implementation("androidx.window:window:1.2.0-beta03")
}

এন্ট্রি পয়েন্ট হল WindowAreaController , যা ডিসপ্লে বা ডিভাইসে ডিসপ্লে এলাকার মধ্যে উইন্ডোগুলি সরানোর সাথে সম্পর্কিত তথ্য এবং আচরণ প্রদান করে। WindowAreaController আপনাকে উপলব্ধ WindowAreaInfo অবজেক্টের তালিকা অনুসন্ধান করতে দেয়।

WindowAreaSession অ্যাক্সেস করতে WindowAreaInfo ব্যবহার করুন, একটি ইন্টারফেস যা একটি সক্রিয় উইন্ডো এলাকা বৈশিষ্ট্য উপস্থাপন করে। একটি নির্দিষ্ট WindowAreaCapability এর প্রাপ্যতা নির্ধারণ করতে WindowAreaSession ব্যবহার করুন।

প্রতিটি ক্ষমতা একটি নির্দিষ্ট WindowAreaCapability.Operation এর সাথে সম্পর্কিত। 1.2.0-beta03 সংস্করণে, Jetpack WindowManager দুটি ধরনের অপারেশন সমর্থন করে:

আপনার অ্যাপের প্রধান ক্রিয়াকলাপে রিয়ার ডিসপ্লে মোড এবং ডুয়াল-স্ক্রিন মোডের জন্য ভেরিয়েবলগুলি কীভাবে ঘোষণা করবেন তার একটি উদাহরণ এখানে দেওয়া হল:

কোটলিন

private lateinit var windowAreaController: WindowAreaController
private lateinit var displayExecutor: Executor
private var windowAreaSession: WindowAreaSession? = null
private var windowAreaInfo: WindowAreaInfo? = null
private var capabilityStatus: WindowAreaCapability.Status =
    WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED

private val dualScreenOperation = WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA
private val rearDisplayOperation = WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA

জাভা

private WindowAreaControllerCallbackAdapter windowAreaController = null;
private Executor displayExecutor = null;
private WindowAreaSessionPresenter windowAreaSession = null;
private WindowAreaInfo windowAreaInfo = null;
private WindowAreaCapability.Status capabilityStatus  =
        WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED;

private WindowAreaCapability.Operation dualScreenOperation =
        WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA;
private WindowAreaCapability.Operation rearDisplayOperation =
        WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA;

আপনার কার্যকলাপের onCreate() পদ্ধতিতে ভেরিয়েবলগুলি কীভাবে শুরু করবেন তা এখানে রয়েছে:

কোটলিন

displayExecutor = ContextCompat.getMainExecutor(this)
windowAreaController = WindowAreaController.getOrCreate()

lifecycleScope.launch(Dispatchers.Main) {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        windowAreaController.windowAreaInfos
            .map { info -> info.firstOrNull { it.type == WindowAreaInfo.Type.TYPE_REAR_FACING } }
            .onEach { info -> windowAreaInfo = info }
            .map { it?.getCapability(operation)?.status ?: WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED }
            .distinctUntilChanged()
            .collect {
                capabilityStatus = it
            }
    }
}

জাভা

displayExecutor = ContextCompat.getMainExecutor(this);
windowAreaController = new WindowAreaControllerCallbackAdapter(WindowAreaController.getOrCreate());
windowAreaController.addWindowAreaInfoListListener(displayExecutor, this);

windowAreaController.addWindowAreaInfoListListener(displayExecutor,
  windowAreaInfos -> {
    for(WindowAreaInfo newInfo : windowAreaInfos){
        if(newInfo.getType().equals(WindowAreaInfo.Type.TYPE_REAR_FACING)){
            windowAreaInfo = newInfo;
            capabilityStatus = newInfo.getCapability(presentOperation).getStatus();
            break;
        }
    }
});

একটি অপারেশন শুরু করার আগে, নির্দিষ্ট ক্ষমতার প্রাপ্যতা পরীক্ষা করুন:

কোটলিন

when (capabilityStatus) {
    WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED -> {
      // The selected display mode is not supported on this device.
    }
    WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNAVAILABLE -> {
      // The selected display mode is not available.
    }
    WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE -> {
      // The selected display mode is available and can be enabled.
    }
    WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE -> {
      // The selected display mode is already active.
    }
    else -> {
      // The selected display mode status is unknown.
    }
}

জাভা

if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED)) {
  // The selected display mode is not supported on this device.
}
else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNAVAILABLE)) {
  // The selected display mode is not available.
}
else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE)) {
  // The selected display mode is available and can be enabled.
}
else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE)) {
  // The selected display mode is already active.
}
else {
  // The selected display mode status is unknown.
}

ডুয়াল-স্ক্রিন মোড

নিম্নলিখিত উদাহরণটি সেশন বন্ধ করে যদি সক্ষমতা ইতিমধ্যে সক্রিয় থাকে, অথবা অন্যথায় presentContentOnWindowArea() ফাংশনকে কল করে:

কোটলিন

fun toggleDualScreenMode() {
    if (windowAreaSession != null) {
        windowAreaSession?.close()
    }
    else {
        windowAreaInfo?.token?.let { token ->
            windowAreaController.presentContentOnWindowArea(
                token = token,
                activity = this,
                executor = displayExecutor,
                windowAreaPresentationSessionCallback = this
            )
        }
    }
}

জাভা

private void toggleDualScreenMode() {
    if(windowAreaSession != null) {
        windowAreaSession.close();
    }
    else {
        Binder token = windowAreaInfo.getToken();
        windowAreaController.presentContentOnWindowArea( token, this, displayExecutor, this);
    }
}

WindowAreaPresentationSessionCallback আর্গুমেন্ট হিসাবে অ্যাপের প্রধান কার্যকলাপের ব্যবহার লক্ষ্য করুন।

এপিআই একটি শ্রোতা পদ্ধতি ব্যবহার করে: যখন আপনি একটি ফোল্ডেবলের অন্য ডিসপ্লেতে বিষয়বস্তু উপস্থাপন করার অনুরোধ করেন, তখন আপনি একটি সেশন শুরু করেন যা শ্রোতার onSessionStarted() পদ্ধতির মাধ্যমে ফিরে আসে। আপনি যখন সেশন বন্ধ করেন, আপনি onSessionEnded() পদ্ধতিতে একটি নিশ্চিতকরণ পাবেন।

শ্রোতা তৈরি করতে, WindowAreaPresentationSessionCallback ইন্টারফেস প্রয়োগ করুন:

কোটলিন

class MainActivity : AppCompatActivity(), windowAreaPresentationSessionCallback

জাভা

public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback

শ্রোতাকে onSessionStarted() , onSessionEnded(), এবং onContainerVisibilityChanged() পদ্ধতি প্রয়োগ করতে হবে। কলব্যাক পদ্ধতি আপনাকে সেশন স্ট্যাটাস সম্পর্কে অবহিত করে এবং সেই অনুযায়ী অ্যাপ আপডেট করতে সক্ষম করে।

onSessionStarted() কলব্যাক একটি যুক্তি হিসাবে একটি WindowAreaSessionPresenter গ্রহণ করে। যুক্তি হল একটি ধারক যা আপনাকে একটি উইন্ডো এলাকা অ্যাক্সেস করতে এবং সামগ্রী প্রদর্শন করতে দেয়। যখন ব্যবহারকারী প্রাথমিক অ্যাপ্লিকেশন উইন্ডোটি ছেড়ে চলে যায় তখন উপস্থাপনাটি সিস্টেম দ্বারা স্বয়ংক্রিয়ভাবে বরখাস্ত করা যেতে পারে, বা WindowAreaSessionPresenter#close() কল করে উপস্থাপনাটি বন্ধ করা যেতে পারে।

অন্যান্য কলব্যাকের জন্য, সরলতার জন্য, কোনো ত্রুটির জন্য শুধুমাত্র ফাংশন বডিতে চেক করুন, এবং স্থিতি লগ করুন:

কোটলিন

override fun onSessionStarted(session: WindowAreaSessionPresenter) {
    windowAreaSession = session
    val view = TextView(session.context)
    view.text = "Hello world!"
    session.setContentView(view)
}

override fun onSessionEnded(t: Throwable?) {
    if(t != null) {
        Log.e(logTag, "Something was broken: ${t.message}")
    }
}

override fun onContainerVisibilityChanged(isVisible: Boolean) {
    Log.d(logTag, "onContainerVisibilityChanged. isVisible = $isVisible")
}

জাভা

@Override
public void onSessionStarted(@NonNull WindowAreaSessionPresenter session) {
    windowAreaSession = session;
    TextView view = new TextView(session.getContext());
    view.setText("Hello world, from the other screen!");
    session.setContentView(view);
}

@Override public void onSessionEnded(@Nullable Throwable t) {
    if(t != null) {
        Log.e(logTag, "Something was broken: ${t.message}");
    }
}

@Override public void onContainerVisibilityChanged(boolean isVisible) {
    Log.d(logTag, "onContainerVisibilityChanged. isVisible = " + isVisible);
}

ইকোসিস্টেম জুড়ে সামঞ্জস্য বজায় রাখতে, ডুয়াল-স্ক্রিন মোড কীভাবে সক্ষম বা অক্ষম করবেন তা ব্যবহারকারীদের নির্দেশ করতে ডুয়াল স্ক্রিন অফিসিয়াল আইকনটি ব্যবহার করুন৷

কাজের নমুনার জন্য, DualScreenActivity.kt দেখুন।

রিয়ার ডিসপ্লে মোড

ডুয়াল-স্ক্রিন মোডের উদাহরণের মতো, একটি toggleRearDisplayMode() ফাংশনের নিম্নলিখিত উদাহরণটি সেশনটি বন্ধ করে দেয় যদি সক্ষমতা ইতিমধ্যে সক্রিয় থাকে, অথবা অন্যথায় transferActivityToWindowArea() ফাংশনকে কল করে:

কোটলিন

fun toggleRearDisplayMode() {
    if(capabilityStatus == WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE) {
        if(windowAreaSession == null) {
            windowAreaSession = windowAreaInfo?.getActiveSession(
                operation
            )
        }
        windowAreaSession?.close()
    } else {
        windowAreaInfo?.token?.let { token ->
            windowAreaController.transferActivityToWindowArea(
                token = token,
                activity = this,
                executor = displayExecutor,
                windowAreaSessionCallback = this
            )
        }
    }
}

জাভা

void toggleDualScreenMode() {
    if(capabilityStatus == WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE) {
        if(windowAreaSession == null) {
            windowAreaSession = windowAreaInfo.getActiveSession(
                operation
            )
        }
        windowAreaSession.close()
    }
    else {
        Binder token = windowAreaInfo.getToken();
        windowAreaController.transferActivityToWindowArea(token, this, displayExecutor, this);
    }
}

এই ক্ষেত্রে, প্রদর্শিত কার্যকলাপটি একটি WindowAreaSessionCallback হিসাবে ব্যবহৃত হয়, যা বাস্তবায়ন করা সহজ কারণ কলব্যাক একটি উপস্থাপক গ্রহণ করে না যা একটি উইন্ডো এলাকায় সামগ্রী দেখানোর অনুমতি দেয় তবে পুরো কার্যকলাপটিকে অন্য এলাকায় স্থানান্তর করে:

কোটলিন

override fun onSessionStarted() {
    Log.d(logTag, "onSessionStarted")
}

override fun onSessionEnded(t: Throwable?) {
    if(t != null) {
        Log.e(logTag, "Something was broken: ${t.message}")
    }
}

জাভা

@Override public void onSessionStarted(){
    Log.d(logTag, "onSessionStarted");
}

@Override public void onSessionEnded(@Nullable Throwable t) {
    if(t != null) {
        Log.e(logTag, "Something was broken: ${t.message}");
    }
}

ইকোসিস্টেম জুড়ে সামঞ্জস্য বজায় রাখতে, রিয়ার ক্যামেরার অফিসিয়াল আইকনটি ব্যবহারকারীদের নির্দেশ করতে ব্যবহার করুন কিভাবে রিয়ার ডিসপ্লে মোড সক্ষম বা অক্ষম করা যায়।

অতিরিক্ত সম্পদ