Katlanabilir ekran modlarını destekleme

Katlanabilir cihazlar benzersiz izleme deneyimleri sunar. Arka ekran modu ve çift ekran modu, katlanabilir cihazlar için arka kamera selfie önizlemesi ve iç ve dış ekranlarda eşzamanlı ancak farklı ekranlar gibi özel ekran özellikleri oluşturmanıza olanak tanır.

Arka ekran modu

Katlanabilir cihazlar genellikle katlandığında yalnızca iç ekran etkin olur. Arka ekran modu, bir etkinliği katlanabilir cihazın dış ekranına taşımanıza olanak tanır. Bu ekran, cihaz açıkken genellikle kullanıcıya dönük değildir. İlgili içeriği oluşturmak için kullanılan iç ekran otomatik olarak kapanır.

Yeni bir uygulama, kamera önizlemesini dış ekranda görüntülemektir. Böylece, Kullanıcılar arka kamerayla selfie çekebilir. Bu kamera arkası kameralarla ön kameraya göre daha iyi performans gösterdi.

Arka ekran modunu etkinleştirmek için kullanıcılar, uygulamanın ekranları değiştirmesine izin vermek üzere bir iletişim kutusuna yanıt verir. Örneğin:

Şekil 1. Arka ekran modunu başlatmaya izin veren sistem iletişim kutusu.

İletişim, sistem tarafından oluşturulur. Sizin herhangi bir geliştirme yapmanız gerekmez. Cihaz durumuna bağlı olarak farklı iletişim kutuları görünür; örneğin sistemin Cihaz kapalıyken kullanıcıları cihazı katlamaya yönlendirir. Bu iletişim kutusunu özelleştiremezsiniz ve farklı OEM'lerin cihazlarında değişiklik gösterebilir.

Pixel Fold'un kamera uygulamasıyla arka ekran modunu deneyebilirsiniz. Örnek göster katlanabilir cihazlarda kamera uygulamanızı optimize etmek için Jetpack WindowManager'ı açın.

Çift ekran modu

Dual Screen modu, ekranın üst kısmında bulunan katlanabilir cihazların her iki ekranında da içerik göstermenize olanak tanır. anlamına gelir. Çift ekran modu, Android 14 çalıştıran Pixel Fold'da kullanılabilir (API düzeyi 34) veya sonraki sürümler.

Dual-screen çevirmeni örnek olarak gösterilebilir.

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

Modları programatik olarak etkinleştirme

Arka ekran moduna ve çift ekran moduna Jetpack'i kullanarak erişebilirsiniz. WindowManager API'leri. Kitaplık sürümü 1.2.0-beta03'ten başlar.

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

Groovy

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

Kotlin

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

Giriş noktası, WindowAreaController öğesidir ve pencereleri ekranlar veya ekranlar arasında taşıma ile ilgili bilgi ve davranış görüntüleyebilirsiniz. WindowAreaController, arama sonuçları sayfasında kullanılabilir WindowAreaInfo nesne.

WindowAreaSession adlı arayüze erişmek için WindowAreaInfo kullanın. etkin bir pencere alanı özelliğini temsil eder. WindowAreaSession hareketini kullanın belirli bir WindowAreaCapability kullanılabilirliği.

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

Burada, arka ekran modu ve özellikleri için değişkenlerin nasıl bildirileceğine Uygulamanızın ana etkinliğinde Dual Screen modu:

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;

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

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şleme başlamadan önce ilgili özelliğin kullanılabilir olup olmadığını 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 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.
}

Çift ekran modu

Aşağıdaki örnek, özellik zaten etkinse oturumu kapatır veya aksi takdirde 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);
    }
}

WindowAreaPresentationSessionCallback bağımsız değişkeni olarak uygulamanın ana etkinliğinin kullanıldığına dikkat edin.

API, dinleyici yaklaşımını kullanır: İçeriği katlanabilir cihazın diğer ekranında göstermek için istek gönderdiğinizde, dinleyicinin onSessionStarted() yöntemi aracılığıyla döndürülen bir oturum başlatırsınız. oturumunda onSessionEnded() yönteminde bir onay alırsınız.

Dinleyiciyi 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(), ve onContainerVisibilityChanged() yöntemlerini uygulaması gerekir. Geri çağırma yöntemleri, ve uygulamayı uygun şekilde güncelleyebilmenizi sağlar.

onSessionStarted() geri çağırması şu şekilde bir WindowAreaSessionPresenter alır: tartışma. Parametre, bir pencere alanına erişmenize ve içerik göstermenize olanak tanıyan kapsayıcıdır. Sunu, sistem tarafından otomatik olarak kapatılabilir Kullanıcı birincil uygulama penceresinden çıktığında veya sunu WindowAreaSessionPresenter#close() aranarak kapatıldı.

Diğer geri çağırmalarda, basitlik açısından işlev gövdesinde hataları 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ık sağlamak için kullanıcılara çift ekran modunu nasıl etkinleştireceklerini veya devre dışı bırakacaklarını belirtmek üzere Dual Screen resmi simgesini kullanın.

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

Arka ekran modu

Çift ekran modu örneğine benzer şekilde, aşağıdaki toggleRearDisplayMode() işlevi örneği, özellik zaten etkinse oturumu kapatır veya aksi takdirde 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örüntülenen etkinlik bir WindowAreaSessionCallback olarak kullanılır. Geri çağırma işlevi, bir pencere alanında içerik göstermeye izin veren bir sunucu almadığı için uygulamak daha kolaydır. Bunun yerine, etkinliğin tamamı başka bir alana aktarılı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ık sağlamak için kullanıcılara arka ekran modunu nasıl etkinleştireceklerini veya devre dışı bırakacaklarını belirtmek üzere Arka Kamera resmi simgesini kullanın.

Ek kaynaklar