Giter VIP home page Giter VIP logo

surface-duo-sdk's Introduction

Surface Duo SDK

This repo contains the source code for the Microsoft Surface Duo SDK.

Please read the code of conduct and contribution guidelines.

Getting Started

When importing the code into Android Studio, use the surface-duo-sdk folder as the base directory of the project. This lets you access the sdk source code and run the sdk samples from within the same project.

Add to your project

  1. Make sure you have mavenCentral() repository in your top level build.gradle file:

    allprojects {
        repositories {
            google()
            mavenCentral()
         }
    }
  2. Add dependencies to the module-level build.gradle file (current version may be different from what's shown here). There are multiple libraries available - for some of them you should reference ScreenManager plus any additional libraries you plan to use:

    ScreenManager

    If you want to choose the version that uses Display Mask API, then you should add the following lines to your gradle file.

    implementation "com.microsoft.device.dualscreen:screenmanager-displaymask:1.0.0-beta4"

    or if you want to choose the version that uses Window Manager API, then you should add the following lines.

    implementation "com.microsoft.device.dualscreen:screenmanager-windowmanager:1.0.0-beta4"

    Bottom navigation

    implementation "com.microsoft.device.dualscreen:bottomnavigation:1.0.0-beta5"

    Fragments handler

    implementation "com.microsoft.device.dualscreen:fragmentshandler:1.0.0-beta5"

    Layouts

    implementation "com.microsoft.device.dualscreen:layouts:1.0.0-beta9"

    Tabs

    implementation "com.microsoft.device.dualscreen:tabs:1.0.0-beta5"

    RecyclerView

    implementation "com.microsoft.device.dualscreen:recyclerview:1.0.0-beta6"

    Ink

    implementation "com.microsoft.device:ink:1.0.0-alpha5"

    Foldable Navigation Component

    def nav_version = "1.0.0-alpha3"
    
    // Java language implementation
    implementation "com.microsoft.device.dualscreen:navigation-fragment:$nav_version"
    implementation "com.microsoft.device.dualscreen:navigation-ui:$nav_version"
    
    // Kotlin
    implementation "com.microsoft.device.dualscreen:navigation-fragment-ktx:$nav_version"
    implementation "com.microsoft.device.dualscreen:navigation-ui-ktx:$nav_version"

    SnackbarContainer

    implementation "com.microsoft.device.dualscreen:snackbar:1.0.0-alpha2"

    Testing

    implementation "com.microsoft.device.dualscreen.testing:testing-kotlin:1.0.0-alpha4"

Useful links

Samples that utilize this SDK

Other Surface Duo developer samples

surface-duo-sdk's People

Contributors

alcere avatar ancirja-m avatar bimiron avatar cesarvaliente avatar conceptdev avatar joyl1216 avatar khalp avatar microsoft-github-operations[bot] avatar microsoftopensource avatar parkerschroeder avatar soalb-m avatar tggmbi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

surface-duo-sdk's Issues

Databinding seems to break SurfaceDuoLayout

I'm working on a custom launcher for the Duo and I've setup data binding within a relatively simple project. When I add binding to the activity however, it breaks the posture change detection. I get the same single screen layout regardless of the device's posture.

Without databinding in Main Activity

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private val vm: CoreViewModel by viewModels()

//    lateinit var singleBinding: FragmentHomeSingleBindingImpl
//    lateinit var dualStartBinding: HomeDualStartBindingImpl
//    lateinit var dualEndBinding: HomeDualEndBindingImpl

    lateinit private var systemTimeBr: SystemTimeBroadcastReceiver

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
//        singleBinding = DataBindingUtil.setContentView(this, R.layout.fragment_home_single)
//        dualStartBinding = DataBindingUtil.setContentView(this, R.layout.home_dual_start)
//        dualEndBinding = DataBindingUtil.setContentView(this, R.layout.home_dual_end)

//        singleBinding.lifecycleOwner = this
//        dualStartBinding.lifecycleOwner = this
//        dualEndBinding.lifecycleOwner = this

//        singleBinding.setVariable(BR.corevm, vm)
//        dualStartBinding.setVariable(BR.corevm, vm)
//        dualEndBinding.setVariable(BR.corevm, vm)

        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    }
...
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <com.microsoft.device.dualscreen.layouts.SurfaceDuoLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"
        app:single_screen_layout_id="@layout/fragment_home_single"
        app:dual_screen_start_layout_id="@layout/fragment_home_dual_start"
        app:dual_screen_end_layout_id="@layout/fragment_home_dual_end">

    </com.microsoft.device.dualscreen.layouts.SurfaceDuoLayout>

</layout>

Single screen mode

image
This behavior is correct.

Dual screen mode

image
This behavior is correct. This is what we should see when unfolded.

With databinding enabled/set up

Single screen mode

image
This behavior is correct.

Dual screen mode

image
This behavior is incorrect, I'm getting the same single screen UI spanned.

All I've done is add these lines back (uncomment) in MainActivity.kt:
singleBinding = DataBindingUtil.setContentView(this, R.layout.fragment_home_single)
singleBinding.lifecycleOwner = this
singleBinding.setVariable(BR.corevm, vm)

And in fragment_home_single.xml

    <data>
        <variable
            name="corevm"
            type="fyi.meld.duo.viewmodels.CoreViewModel" />
    </data>
    <TextView
        android:id="@+id/time_view"
        ...
        android:text="@{corevm.clockData.time}"
        ... />

    <TextView
        android:id="@+id/meridian_indicator_view"
        ...
        android:text="@{corevm.clockData.meridian_indicator}"
        ... />

    <TextView
        android:id="@+id/date_view"
        ...
        android:text="@{corevm.clockData.date}"
        ... />

Other notes

  • The full repository is here. Be sure to check out the screen_transition_bug branch. You can try repro-ing it the same way with the full project.
  • I figure I should probably be setting up the binding in the HomeSingleFragment, but I just haven't gotten around to it yet.
  • I see that there is some special handling required for fragments to support screen state transitions, but I'm also able to repro this exact issue regardless of whether or not the inputs to SurfaceDuoLayout are fragments or just regular old layouts.

Please let me know if there's more context I can provide.

Thanks!

Add callback to check what part of home screen is occluded

Hi there, I hope this is the right place to ask a compatibility question about home screen apps. I'm one of the developers of the home screen app Niagara Launcher, and lately, we're trying to optimize our UX for foldable devices, including the Surface Duo.

The Problem

I noticed that when the Duo is unfolded, the home screen is displayed on both displays. If you launch an app, it occupies one of the two screens by default. Now half of our home screen is occluded by that app. I tried to find a callback method that notifies us about what part of the app is currently visible/occluded to the user but unfortunately to no avail. Microsoft Launcher, on the other hand, rearranges its layout after launching an app. I wish there was a public method for third-party launchers to check what parts of the home screen are visible to the user and what parts are occluded by other apps.

What callbacks I tried but did not fire on when the home screen is partially occluded:

  • ScreenInfoListener.onScreenInfoChanged(...) (from com.microsoft.device.dualscreen:screenmanager-windowmanager:1.0.0-beta4)
  • windowInfoRepository.windowLayoutInfo (from androidx.window:window:1.0.0-beta02)
  • OnApplyWindowInsetsListener.onApplyWindowInsets(...) (from the Android framework)

Illustrations

Niagara Launcher on both screens

Screenshot_1630572941

Half of Niagara's home screen is occluded when an app is launched

Screenshot_1630572961
Screenshot_1630572968

Microsoft Launcher can readjust its layout (e.g. the dock at the bottom) when an app is launched

Screenshot_1630573025
Screenshot_1630573028

Additional details

I tested this on the Surface Duo Emulator (SurfaceDuoEmulator_2021.816.1_windows).

[FoldableLayout] Remove FoldingFeature representation that the component renders.

Currently FoldableLayout component draws the representation of the emulator/device's FoldingFeature`.

E.g. when you run the FoldableLayout sample in a Surface Duo device/emulator, you can see how there is a colored area that represents the physical hinge.

The FoldingFeaure representation shouldn't be drawn since it can collide with app's specific UI.

SurfaceDuoLayout and startActivity

Hello,

I have very simple app - on activity with only a SurfaceDuoLayout as simple as this:

<com.microsoft.device.dualscreen.layouts.SurfaceDuoLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:single_screen_layout_id="@layout/view_single"
    app:dual_screen_start_layout_id="@layout/view_left"
    app:dual_screen_end_layout_id="@layout/view_right"
    app:tools_screen_mode="dual_screen">

It all works when I start the app:
app starts in single screen, drag it to the hinge and it becomes dual screen all works fine.
Now if create the same activity by startActivity it always starts as single mode (and I can even not drag it again), app is in duo mode so as a result I got same activity spanned as it displays the single view

onScreenInfoChanged seems correct (getting single/duo as expected) but the following code inside SurfaceDuoLayout gets confused:

setupViewModel method viewModel is single for the second start?

Any idea what's wrong?

[FragmentsHandler] Swapping bundler not working in multi-window mode after closing the device

Prerequisite: Other Foldable Devices (ex. Samsung Fold 2)

Steps to reproduce:

  1. Open the FragmentsHandler Sample on multi window mode on other foldable devices (ex. Samsung Fold 2)
  2. Close the device and open it again
  3. Change the app to cover the entire display area

Expectation: The DualStartFragment and DualEndFragment are visible

Actual: The SingleScreenFragment and DualEndFragment are visible

Cause: onActivityPreCreated lifecycle callback is called twice from time to time

[FragmentsHandler] Swapping bundler not working on multi window mode when device is rotated

Prerequisite: Other Foldable Devices (ex. Samsung Fold 2)

Steps to reproduce:

  1. Open the FragmentsHandler Sample on multi window mode on other foldable devices (ex. Samsung Fold 2)
  2. Rotate the device a couple of times
  3. Change the app to cover the entire display area

Expectation: The DualStartFragment and DualEndFragment are visible

Actual: The SingleScreenFragment and DualEndFragment are visible

Cause: onActivityPreCreated lifecycle callback is called twice from time to time

Possible Solution:

// Other companion properties and functions
    private const val PRE_CREATED_CALL_DELAY = 500
// Other properties
    private var lastActivityPreCreatedTimestamp = System.currentTimeMillis() - PRE_CREATED_CALL_DELAY

    override fun onActivityPreCreated(activity: Activity, savedInstanceState: Bundle?) {
        val currentTimestamp = System.currentTimeMillis()
        if (currentTimestamp - lastActivityPreCreatedTimestamp < PRE_CREATED_CALL_DELAY) {
            super.onActivityPreCreated(activity, savedInstanceState)
            return
        }
        
        // .....
    }

[BUG] Xamarin Forms Crash Log: System.NullReferenceException at PlatformConfigurationExtensions.OnThisPlatform

πŸ› Describe the bug

Crash log on Surface Duo devices only (Android 11, not reproducible but have gotten the log multiple times). Any ideas what could be causing this?

PlatformConfigurationExtensions.OnThisPlatform[T] (T element)
System.NullReferenceException: Object reference not set to an instance of an object

PlatformConfigurationExtensions.OnThisPlatform[T] (T element)
FragmentContainer.OnPause ()
Fragment.n_OnPause (System.IntPtr jnienv, System.IntPtr native__this)
(wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.129(intptr,intptr)

βœ”οΈ Expected behavior

Either a better exception or no exception at all

πŸͺœ Steps to reproduce

Not reproducible :(

[BUG] [1.0.1-alpha07] Incompatibility with "androidx.navigation:navigation-compose:2.6.0"

πŸ› Describe the bug

I found that after updating the navigation-compose dependency to 2.6.0 theΒ navigateToPane2() function crashes with the following log:

FATAL EXCEPTION: main Process: com.xxx.xxx, PID: 12507 java.lang.NoSuchMethodError: No virtual method getBackQueue()Lkotlin/collections/ArrayDeque; in class Landroidx/navigation/NavHostController; or its super classes (declaration of 'androidx.navigation.NavHostController' appears in /data/app/~~phM2qZ5vae1iOopB_iXCPg==/com.xxx.xxx-QMpXgWBhbZ6qhfai2lCApw==/base.apk!classes15.dex) at com.microsoft.device.dualscreen.twopanelayout.twopanelayout.TwoPaneLayoutCoreKt$SinglePaneContainer$3.invoke(TwoPaneLayoutCore.kt:72) at com.microsoft.device.dualscreen.twopanelayout.twopanelayout.TwoPaneLayoutCoreKt$SinglePaneContainer$3.invoke(TwoPaneLayoutCore.kt:71)

⚠️ Current behavior

FATAL EXCEPTION: main Process: com.xxx.xxx, PID: 12507 java.lang.NoSuchMethodError: No virtual method getBackQueue()Lkotlin/collections/ArrayDeque; in class Landroidx/navigation/NavHostController; or its super classes (declaration of 'androidx.navigation.NavHostController' appears in /data/app/~~phM2qZ5vae1iOopB_iXCPg==/com.xxx.xxx-QMpXgWBhbZ6qhfai2lCApw==/base.apk!classes15.dex) at com.microsoft.device.dualscreen.twopanelayout.twopanelayout.TwoPaneLayoutCoreKt$SinglePaneContainer$3.invoke(TwoPaneLayoutCore.kt:72) at com.microsoft.device.dualscreen.twopanelayout.twopanelayout.TwoPaneLayoutCoreKt$SinglePaneContainer$3.invoke(TwoPaneLayoutCore.kt:71)

βœ”οΈ Expected behavior

No crash

πŸͺœ Steps to reproduce

  1. Add the following dependencies
    androidx.navigation:navigation-compose:2.6.0
    com.microsoft.device.dualscreen:twopanelayout:1.0.1-alpha07
  2. Use the function navigateToPane2()
  3. App crashes

πŸ“± Tech info

  • Name of the library: com.microsoft.device.dualscreen:twopanelayout
  • Library/App version: 1.0.1-alpha07
  • Device/emulator version/model: Pixel 6
  • OS: SDK 34

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.