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

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

बैक डिसप्ले मोड

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

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

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

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

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

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

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

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

इसका एक उदाहरण, ड्यूअल स्क्रीन में अनुवादक मोड है.

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

प्रोग्राम के हिसाब से मोड चालू करना

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

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

Groovy

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

Kotlin

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

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

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

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

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

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

WindowAreaController.windowAreaInfos

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 MainActivity : AppCompatActivity(), windowAreaPresentationSessionCallback

Java

public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback

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

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

अन्य कॉलबैक के लिए, फ़ंक्शन बॉडी में किसी भी गड़बड़ी की जांच करें और स्थिति को लॉग करें:

Kotlin

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

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

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

काम करने वाले सैंपल के लिए, 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 के तौर पर इस्तेमाल किया जाता है. इसे लागू करना आसान है, क्योंकि कॉलबैक को ऐसा प्रेजेंटर नहीं मिलता जो विंडो एरिया पर कॉन्टेंट दिखा सके. इसके बजाय, पूरी गतिविधि को किसी दूसरे एरिया में ट्रांसफ़र कर दिया जाता है:

Kotlin

override fun onSessionStarted() {
    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}");
    }
}

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

अन्य संसाधन