फ़ोल्ड किए जा सकने वाले डिसप्ले मोड के साथ काम करता है

फ़ोल्ड किए जा सकने वाले डिवाइसों से, वीडियो देखने का खास अनुभव मिलता है. रियर डिसप्ले मोड और ड्यूअल‑स्क्रीन मोड की मदद से, फ़ोल्ड किए जा सकने वाले डिवाइसों के लिए, डिसप्ले की खास सुविधाएं बनाई जा सकती हैं. जैसे, रियर‑कैमरा सेल्फ़ी का प्रीव्यू और इनर और आउटर स्क्रीन पर एक साथ अलग-अलग डिसप्ले.

रियर डिसप्ले मोड

आम तौर पर, फ़ोल्ड किए जा सकने वाले डिवाइस को अनफ़ोल्ड करने पर, सिर्फ़ इनर स्क्रीन चालू होती है. रियर डिसप्ले मोड की मदद से, किसी ऐक्टिविटी को फ़ोल्ड किए जा सकने वाले डिवाइस की आउटर स्क्रीन पर ले जाया जा सकता है. आम तौर पर, डिवाइस को अनफ़ोल्ड करने पर, यह स्क्रीन उपयोगकर्ता से दूसरी तरफ़ होती है. इनर डिसप्ले अपने-आप बंद हो जाता है.

इसका एक नया इस्तेमाल यह है कि आउटर स्क्रीन पर कैमरे का प्रीव्यू दिखाया जाए. इससे उपयोगकर्ता, रियर कैमरे से सेल्फ़ी ले सकते हैं. आम तौर पर, रियर कैमरे से फ़्रंट कैमरे के मुकाबले बेहतर तस्वीरें ली जा सकती हैं.

रियर डिसप्ले मोड चालू करने के लिए, उपयोगकर्ता किसी डायलॉग बॉक्स में जवाब देकर, ऐप्लिकेशन को स्क्रीन स्विच करने की अनुमति देते हैं. उदाहरण के लिए:

पहली इमेज. रियर डिसप्ले मोड चालू करने की अनुमति देने के लिए, सिस्टम का डायलॉग बॉक्स.

डायलॉग बॉक्स सिस्टम बनाता है. इसलिए, आपको इसे बनाने की ज़रूरत नहीं होती. डिवाइस की स्थिति के हिसाब से, अलग-अलग डायलॉग बॉक्स दिखते हैं. उदाहरण के लिए, अगर डिवाइस बंद है, तो सिस्टम उपयोगकर्ताओं को डिवाइस अनफ़ोल्ड करने के लिए कहता है. डायलॉग बॉक्स को पसंद के मुताबिक नहीं बनाया जा सकता. साथ ही, यह अलग-अलग ओईएम के डिवाइसों पर अलग-अलग दिख सकता है.

Pixel Fold के कैमरा ऐप्लिकेशन के साथ, रियर डिसप्ले मोड आज़माया जा सकता है. Jetpack WindowManager की मदद से, फ़ोल्ड किए जा सकने वाले डिवाइसों पर अपने कैमरा ऐप्लिकेशन को ऑप्टिमाइज़ करें कोडलैब में, इसे लागू करने का तरीका देखें.

ड्यूअल-स्क्रीन मोड

ड्यूअल-स्क्रीन मोड की मदद से, फ़ोल्ड किए जा सकने वाले डिवाइस के दोनों डिसप्ले पर एक साथ कॉन्टेंट दिखाया जा सकता है. ड्यूअल‑स्क्रीन मोड, Android 14 (एपीआई लेवल 34) या इसके बाद वाले वर्शन पर काम करने वाले Pixel Fold पर उपलब्ध है.

ड्यूअल-स्क्रीन इंटरप्रेटर, इसके इस्तेमाल का एक उदाहरण है.

दूसरी इमेज. ड्यूअल-स्क्रीन इंटरप्रेटर, फ़्रंट और रियर डिसप्ले पर अलग-अलग कॉन्टेंट दिखाता है.

प्रोग्राम के ज़रिए मोड चालू करना

लाइब्रेरी के वर्शन 1.2.0-beta03 से, Jetpack WindowManager के एपीआई के ज़रिए, रियर डिसप्ले मोड और ड्यूअल‑स्क्रीन मोड को ऐक्सेस किया जा सकता है.

अपने ऐप्लिकेशन के मॉड्यूल की build.gradle फ़ाइल में, WindowManager की डिपेंडेंसी जोड़ें:

Kotlin

dependencies {
    // Define window_version in your project's build configuration.
    implementation("androidx.window:window:$window_version")
}

शानदार

dependencies {
    // TODO: Define window_version in your project's build configuration.
    implementation "androidx.window:window:$window_version"
}

एंट्री पॉइंट, WindowAreaController है. यह किसी डिवाइस पर, डिसप्ले के बीच या डिसप्ले एरिया के बीच विंडो ले जाने से जुड़ी जानकारी और व्यवहार उपलब्ध कराता है. WindowAreaController की मदद से, उपलब्ध WindowAreaInfo ऑब्जेक्ट की सूची के बारे में क्वेरी की जा सकती है.

WindowAreaInfo का इस्तेमाल करके, WindowAreaSession को ऐक्सेस किया जा सकता है. यह एक ऐसा इंटरफ़ेस है जो चालू विंडो एरिया की सुविधा को दिखाता है. WindowAreaSession का इस्तेमाल करके, किसी खास WindowAreaCapability की उपलब्धता का पता लगाया जा सकता है.

हर सुविधा, किसी खास WindowAreaCapability.Operation से जुड़ी होती है. वर्शन 1.2.0-beta03 में, Jetpack WindowManager दो तरह के ऑपरेशन के साथ काम करता है:

यहां एक उदाहरण दिया गया है, जिसमें बताया गया है कि आपके ऐप्लिकेशन की मुख्य ऐक्टिविटी में, रियर डिसप्ले मोड और ड्यूअल‑स्क्रीन मोड के लिए वैरिएबल कैसे तय किए जाते हैं:

Kotlin

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

Java

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() तरीके में, वैरिएबल को कैसे शुरू किया जाता है:

Kotlin

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

Java

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

कोई ऑपरेशन शुरू करने से पहले, खास सुविधा की उपलब्धता की जांच करें:

Kotlin

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

Java

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() फ़ंक्शन कॉल किया जाता है:

Kotlin

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

Java

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

` WindowAreaPresentationSessionCallback` आर्ग्युमेंट के तौर पर, ऐप्लिकेशन की मुख्य ऐक्टिविटी के इस्तेमाल पर ध्यान दें.

एपीआई, लिसनर के तरीके का इस्तेमाल करता है: जब आप फ़ोल्ड किए जा सकने वाले डिवाइस के दूसरे डिसप्ले पर कॉन्टेंट दिखाने का अनुरोध करते हैं, तो एक सेशन शुरू होता है. यह सेशन, लिसनर के onSessionStarted() तरीके से वापस मिलता है. सेशन बंद करने पर, आपको onSessionEnded() तरीके में पुष्टि मिलती है.

लिसनर बनाने के लिए, WindowAreaPresentationSessionCallback इंटरफ़ेस लागू करें:

Kotlin

class ExampleActivity : ComponentActivity(), WindowAreaPresentationSessionCallback {

Java

public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback

लिसनर को onSessionStarted(), onSessionEnded(), और onContainerVisibilityChanged() तरीके लागू करने होंगे. कॉलबैक के तरीके, आपको सेशन के स्टेटस के बारे में सूचना देते हैं. साथ ही, इनकी मदद से ऐप्लिकेशन को अपडेट किया जा सकता है.

onSessionStarted() कॉलबैक को, WindowAreaSessionPresenter एक आर्ग्युमेंट के तौर पर मिलता है. यह आर्ग्युमेंट, वह कंटेनर है जिसकी मदद से विंडो एरिया को ऐक्सेस किया जा सकता है और कॉन्टेंट दिखाया जा सकता है. जब उपयोगकर्ता, मुख्य ऐप्लिकेशन की विंडो से बाहर निकलता है, तो सिस्टम, प्रज़ेंटेशन को अपने-आप खारिज कर सकता है . इसके अलावा, प्रज़ेंटेशन को बंद करने के लिए, WindowAreaSessionPresenter#close() को कॉल किया जा सकता है.

अन्य कॉलबैक के लिए, आसानी से समझने के लिए, फ़ंक्शन के मुख्य हिस्से में सिर्फ़ गड़बड़ियों की जांच करें और स्टेटस लॉग करें:

Kotlin

override fun onSessionStarted(session: WindowAreaSessionPresenter) {
    windowAreaSession = session
    session.setContentView(ComposeView(session.context).apply {
        setContent {
            MyScreen()
        }
    })
}

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

Java

@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() फ़ंक्शन कॉल किया जाता है:

Kotlin

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

Java

void toggleRearDisplayMode() {
    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 के तौर पर किया जाता है.

रियर डिसप्ले एपीआई, लिसनर के तरीके के साथ काम करता है: जब आप कॉन्टेंट को दूसरे डिसप्ले पर ले जाने का अनुरोध करते हैं, तो एक सेशन शुरू होता है. यह सेशन, लिसनर के onSessionStarted() तरीके से वापस मिलता है. अगर आपको इनर (और बड़े) डिसप्ले पर वापस जाना है, तो सेशन बंद करें. इसके बाद, आपको onSessionEnded() तरीके में पुष्टि मिलेगी.

Kotlin

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

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

Java

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

इकोसिस्टम में एक जैसा अनुभव देने के लिए, रियर कैमरा के आधिकारिक आइकॉन का इस्तेमाल करें. इससे उपयोगकर्ताओं को यह पता चलेगा कि रियर डिसप्ले मोड को कैसे चालू या बंद किया जाता है.

अन्य संसाधन