Katlanabilir ekran modlarını destekleme

Katlanabilir cihazlar benzersiz bir izleme deneyimi sunar. Arka ekran modu ve Dual Screen modu, katlanabilir cihazlar için arka kamera selfie önizlemesi ve iç ve dış ekranlarda aynı anda farklı ekranlar gibi özel ekran özellikleri oluşturmanıza olanak tanır.

Arka ekran modu

Genellikle katlanabilir cihaz açıldığında yalnızca iç ekran etkindir. Arka ekran modu, bir aktiviteyi katlanabilir cihazın dış ekranına taşımanızı sağlar. Cihaz katlanmış durumdayken genellikle kullanıcıya bakmayan yüzler. İç ekran otomatik olarak kapanır.

Yeni bir uygulama, kamera önizlemesini dış ekranda görüntülemektir. Bu sayede kullanıcılar arka kamerayla selfie çekebilir. Bu da genellikle çok daha iyi resim çekme performansı sunar.

Arka ekran modunu etkinleştirmek için kullanıcılar bir iletişim kutusuna yanıt vererek uygulamanın ekranlar arasında geçiş yapmasına izin verir. Örneğin:

Şekil 1. Arka ekran modunun başlatılmasına izin veren sistem iletişim kutusu.

İletişim, sistem tarafından oluşturulur. Bu nedenle herhangi bir geliştirme yapmanız gerekmez. Cihaz durumuna bağlı olarak farklı iletişim kutuları görünür; örneğin, Cihaz kapalıysa sistem, kullanıcıları cihazı açmaya yönlendirir. İletişim kutusunu özelleştiremezsiniz ancak farklı OEM'lerin cihazlarına göre değişiklik gösterebilir.

Pixel Fold'un kamera uygulamasıyla arka ekran modunu deneyebilirsiniz. Kamera deneyiminizi keşfetme başlıklı codelab'deki örnek uygulamaya göz atın.

Dual Screen modu

Dual Screen modu, katlanabilir cihazların her iki ekranında aynı anda içerik göstermenize olanak tanır. Dual Screen modu, Android 14 (API düzeyi 34) veya sonraki sürümleri çalıştıran Pixel Fold'da kullanılabilir.

Dual Screen çevirmen gibi kullanım alanları örnek olarak verilebilir.

Şekil 2. Ön ve arka ekranlarda farklı içerikler gösteren Dual Screen çevirmen.

Modları programatik olarak etkinleştirme

Kitaplık sürümü 1.2.0-beta03'ten itibaren Jetpack WindowManager API'lerini kullanarak arka ekran modu ve Dual Screen moduna erişebilirsiniz.

WindowManager bağımlılığını uygulamanızın build.gradle modülüne ekleyin:

Eski

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

Kotlin

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

Giriş noktası WindowAreaController ise , pencerelerin ekranlar veya bir cihazdaki görüntüleme alanları arasında taşınmasıyla ilgili bilgiler ve davranışlar sağlar. WindowAreaController, mevcut projenizde sunulan WindowAreaInfo nesneler'i tıklayın.

WindowAreaInfo işlevini kullanarak WindowAreaSession, etkin bir pencere alanı özelliğini temsil eden arayüz. Belirli bir özelliğin kullanılabilirliğini belirlemek için WindowAreaSession WindowAreaCapability

Her özellik belirli bir WindowAreaCapability.Operation ile ilişkilidir. 1.2.0-beta03 sürümünde Jetpack WindowManager iki tür işlemi destekler:

Aşağıda, uygulamanızın ana etkinliğinde arka ekran modu ve çift ekran modu için değişkenleri nasıl beyan edeceğinize dair bir örnek verilmiştir:

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;

Etkinliğinizin onCreate() yöntemindeki değişkenleri nasıl başlatacağınız aşağıda açıklanmıştır:

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

Bir işlemi başlatmadan önce, belirli bir özelliğin kullanılabilirliğini kontrol edin:

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 currently available to be enabled.
    }
    WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE -> {
      // The selected display mode is currently available to 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 currently available to be enabled.
}
else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE)) {
  // The selected display mode is currently available to 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.    
}

Dual Screen modu

Aşağıdaki örnek, özellik zaten etkinse oturumu kapatır. veya presentContentOnWindowArea() işlevini çağırır:

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

Uygulamanın ana etkinliğinin WindowAreaPresentationSessionCallback olarak kullanıldığına dikkat edin.

API bir işleyici yaklaşımı kullanır: içeriğin sunulması için istekte bulunduğunuzda diğer ekrandayken geri gelen bir oturum başlatırsınız. dinleyicinin onSessionStarted() yöntemiyle desteklenir. Oturumu kapattığınızda onSessionEnded() yönteminde bir onay alırsınız.

İşleyici oluşturmak için WindowAreaPresentationSessionCallback arayüzünü uygulayın:

Kotlin

class MainActivity : AppCompatActivity(), windowAreaPresentationSessionCallback

Java

public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback

Dinleyicinin onSessionStarted(), onSessionEnded(), öğesini uygulaması gerekir ve onContainerVisibilityChanged() yöntemlerinden birini kullanıyor. Geri çağırma yöntemleri, oturum durumunu size bildirir ve uygulamayı uygun şekilde güncellemenize olanak tanır.

onSessionStarted()Geri çağırma, bağımsız değişken olarak bir WindowAreaSessionPresenter alır. Bağımsız değişken, bir pencere alanına erişmenize ve içeriği göstermenize olanak tanıyan kapsayıcıdır. Kullanıcı birincil uygulama penceresinden ayrıldığında sunu sistem tarafından otomatik olarak kapatılabilir veya WindowAreaSessionPresenter#close() çağrısı yapılarak sunu kapatılabilir.

Diğer geri çağırmalarda, kolaylık sağlamak amacıyla işlev gövdesinde hata olup olmadığını kontrol edin ve durumu günlüğe kaydedin:

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

Ekosistem genelinde tutarlılığı korumak amacıyla, kullanıcılara Dual Screen modunu nasıl etkinleştireceklerini veya devre dışı bırakacaklarını göstermek için Çift Ekran resmi simgesini kullanın.

Çalışan bir örnek için DualScreenActivity.kt sayfasına göz atın.

Arka ekran modu

Dual Screen modu örneğine benzer şekilde aşağıdaki toggleRearDisplayMode() örneği işlev zaten etkinse oturumu kapatır. veya başka bir şekilde transferActivityToWindowArea() işlevini çağırır:

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

Bu durumda, gösterilen etkinlik WindowAreaSessionCallback, olarak kullanılır. Bu yöntem, geri çağırma için bir sunucu gelmediğinden uygulanması daha kolaydır bir pencere alanında içerik gösterilmesine izin verir, ancak bunun yerine tüm etkinliği başka bir alana aktarır:

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

Ekosistem genelinde tutarlılığı korumak için Arka Kamera resmi simgesini kullanarak kullanıcılara arka ekran modunu nasıl etkinleştireceklerini veya devre dışı bırakacaklarını gösterin.

Ek kaynaklar

ziyaret edin. ziyaret edin.