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

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

प्रोग्राम के हिसाब से मोड चालू करें
लाइब्रेरी के वर्शन 1.2.0-beta03 की शुरुआत में, Jetpack WindowManager एपीआई की मदद से, रीयर डिसप्ले मोड और ड्यूअल-स्क्रीन मोड को ऐक्सेस किया जा सकता है.
अपने ऐप्लिकेशन के मॉड्यूल 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 दो तरह की कार्रवाइयों के साथ काम करता है:
WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA
, जिसका इस्तेमाल ड्यूअल‑स्क्रीन मोड चालू करने के लिए किया जाता हैWindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA
, जिसका इस्तेमाल पीछे की सीट पर मौजूद डिसप्ले मोड को चालू करने के लिए किया जाता है
यहां ऐप्लिकेशन की मुख्य गतिविधि में, पीछे के डिसप्ले मोड और ड्यूअल-स्क्रीन मोड के लिए वैरिएबल का एलान करने का उदाहरण दिया गया है:
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}");
}
}
पूरे नेटवर्क पर एक जैसा अनुभव देने के लिए, रियर कैमरा के आधिकारिक आइकॉन का इस्तेमाल करें. इससे, उपयोगकर्ताओं को यह पता चलेगा कि रियर डिसप्ले मोड को कैसे चालू या बंद किया जा सकता है.
अन्य संसाधन
- Jetpack WindowManager की मदद से, फ़ोल्ड किए जा सकने वाले डिवाइसों पर अपने कैमरा ऐप्लिकेशन को ऑप्टिमाइज़ करना कोडलैब
androidx.window.area
पैकेज की खास जानकारी- Jetpack WindowManager का सैंपल कोड: