7

The new ActivityOptions setLaunchDisplayId (int launchDisplayId) function in Android-O seems to always crash my app when I try to launch an activity intent.

Both when I launch activities from my own app and when I try to launch other apps i.e. Chrome Canary.

Does anyone know if this is a general problem with the new API's or am I missing something:

A small snippet of my code is below:

options.setLaunchDisplayId(1); startActivity(intent, options);

NOTE I was testing with 'simulate a second screen' enabled (@1080p if it matters).

UPDATE I have tried the ADB command adb shell start com.chrome.canary --display 1, and I get the message:

start: must be root

Smiler
  • 1,316
  • 4
  • 12
  • 18
  • How have you determined that `1` is the correct number? When I use the simulated second screen, the ID of that second screen is `2` AFAICT. I don't crash, but I'm also not getting the activity started on that display. BTW, you forgot `am` in `adb shell am start`. – CommonsWare Mar 25 '17 at 18:54
  • I've connected to the external display with the new API by getting the Presentation display ID. But I am still struggling to find a way to interact with the second screen. With the older API's I could only use my own activities so I could just pass input from my phone to the second screens UI, but that is proving difficult when attempting to complete that with the new API's as I am now trying to interact with other apps. – Smiler Mar 25 '17 at 19:15
  • Following steps which is not working for me 1.connect hdmi cable to mobile(not sure can use USB as well) 2.make device in root and give following command (expect app is installed) and not seen that app is launching on secondary(Multiple display feature ) it's just reflecting mobile display as it is because connected hdmi cable adb shell am start com.Chrome.Canary --display 1 Please suggest any other way or any command to make it work? – prathima Jul 18 '17 at 16:25

3 Answers3

6

I have connected to the second screen via the new API's with the code below, but as of yet have no way of interacting with it.

 Bundle bdl;
 MediaRouter mediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
 MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
 if (route != null) {
     Display presentationDisplay = route.getPresentationDisplay();
     bdl = ActivityOptions.makeClipRevealAnimation(mView, left, top, width, height).setLaunchBounds(rect).setLaunchDisplayId(presentationDisplay.getDisplayId()).toBundle();
     Bundle optsBundle = true ? bdl : null;
     Intent intent = new Intent(mContext, SecondaryActivity.class);
     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     mContext.startActivity(intent, optsBundle);
 }
Adeel Ahmad
  • 939
  • 1
  • 10
  • 20
Smiler
  • 1,316
  • 4
  • 12
  • 18
  • What do you mean by "have no way of interacting with it"? – CommonsWare Mar 25 '17 at 19:34
  • When I have a keyboard or mouse connected to my device it only interacts with the devices own display, I can't forward that input device to interact with the apps running on display 2. I am still looking if there is way to overcome this barrier and enable fully functioning Android apps on my external display. – Smiler Mar 25 '17 at 19:38
  • That's [a documented limitation](https://developer.android.com/preview/api-overview.html#mds): "Only one activity at a time can be in the resumed state, even if the app has multiple displays. The activity with focus is in the resumed state; all other visible activities are paused, but not stopped." This is not significantly different than regular multi-window. My guess is that, akin to picture-in-picture, the idea is that you put something on the external display that does not itself require user input. – CommonsWare Mar 25 '17 at 19:40
  • I am having difficulty reproducing your results -- I just get the activity launching normally, not into the secondary display. The only thing missing in my implementation compared to the one in your answer is `setLaunchBounds()`. What are you using for `rect`? – CommonsWare Mar 25 '17 at 19:44
  • I kind of understand the idea of limiting media apps to be controlled remotely from the device. But as we can now launch apps such as 'Play store' or 'System settings' on the second screen, it makes sense to try and interact with those apps. This could potentially enable users to make use of any purchased app on a larger screen to up their productivity or enable large screen gaming powered by Android!. *EDIT* my code may be a little messy at the moment as I have been doing a heck of alot of trial and error, but I'll post my 'rect' in the post below – Smiler Mar 25 '17 at 19:44
  • NOTE that I was also trying to test freeform so some of that code is still in there "int width1 = display.getWidth() / (4); int width2 = display.getWidth() - width1; int height1 = display.getHeight() / (4); int height2 = display.getHeight() - height1; Rect rect = new Rect( width1, height1, width2, height2 );" – Smiler Mar 25 '17 at 19:48
  • Hmmm... still no luck. Is there anything unusual for `SecondaryActivity` in your manifest? I have `android:supportsPictureInPicture="true"` and `android:resizeableActivity="true"`, neither of which helped. – CommonsWare Mar 25 '17 at 19:51
  • I have tried this with both 'SecondActivity' & third party app intents and it works on both. – Smiler Mar 25 '17 at 19:53
  • Aha! Starting some other activity (one from Settings) works. Now I just need to figure out what's busted with my own activity. Many thanks! – CommonsWare Mar 25 '17 at 19:57
  • No problems 'CW', I think that you have bee helpful on here to me several times during my time as an Android dev, so I hope that I can be of help to you too!. Good luck with Android-O developments!. I hope this can also help with your presentation library if you still work on that!. – Smiler Mar 25 '17 at 20:01
  • OK, to launch my own activity, I needed to add `Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_MULTIPLE_TASK`, not just `Intent.FLAG_ACTIVITY_NEW_TASK`. Then, it works fine. With regards to my presentation library, I don't think that this feature changes that library, but it makes that library less important. We're running into problems with my `PresentationService` on 7.1, though, and so this feature might be able to supplant my own "control an external display from the background" stuff. Anyway, thanks again! – CommonsWare Mar 25 '17 at 20:29
  • 1
    Just remember that if you are launching third party apps then in order to close them you may have to clear them from recents on your device – Smiler Mar 25 '17 at 20:43
  • Following steps which is not working for me 1.connect hdmi cable to mobile(not sure can use USB as well) 2.make device in root and give following command (expect chrome canary app is installed) and not seen that app is launching on secondary(Multiple display feature ) it's just reflecting mobile display as it is because connected hdmi cable adb shell am start com.Chrome.Canary --display 1 Please suggest any other way or any command to make it work? – prathima Jul 18 '17 at 16:37
  • Hi smiler, as a end user how to enable this feature? Connected TV to phone using hdmi cable and ran the adb command as follow adb shell am start --display could you please provide a example command and clear procedure to show "setting" app in secondary display – prathima Jul 20 '17 at 14:17
  • @prathima: if you are rooted, replace with "com.google.android.apps.chrome.Main" (without quotes) and with 1 (depending upon what id your external display is - typically the phones display will be id: 0). Of course the activity in this example is chrome but you can change that. *Note* I haven't got the tools to test this adb command just now, so I'm not 100% sure if it will will work for you... – Smiler Jul 21 '17 at 15:34
  • @ Smiler: as phone is connected to HDMI cable to TV ,full phone display will be reflected in TV aswell but "Multi-Display" feature should be able to launch the app by using full TV display and on primary it should not show ,here in my case after running "adb shell am start com.android.chrome --display 1" chrome app is able to launch on primary and same reflected on TV – prathima Jul 24 '17 at 05:25
  • @prathima: Sorry that I can't help with the adb command. I don't have the time to test adb commands at the moment. All that I can recommend for now is that you build a basic app in Android Studio and trigger the code I added above in onCreate(). You will see your phone's display being mirrored on the external display until you launch the app on the external display. – Smiler Jul 25 '17 at 06:10
  • Launching app in secondary display is working,but it consumes around 2 sec & delay the launcher activity from primary disaply by 2 sec.Any workaround how to avoid it. – Pranesh Sahu Jul 04 '20 at 17:48
6

Here's a simplified answer which is working for me, built off of @Smiler. I tested this via a Button click in my MainActivity. Thanks for the help!

    ((Button) findViewById(R.id.launchTopScreen)).setOnClickListener(v -> {
        Intent intent = getPackageManager().getLaunchIntentForPackage("com.example.new.app");
        intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
        ActivityOptions options = ActivityOptions.makeBasic().setLaunchDisplayId(1);
        startActivity(intent, options.toBundle());
    });

The Intent.FLAG_ACTIVITY_NEW_TASK is extremely important in order to have the new application launch on a different display. Otherwise it'll launch in the same task stack, on the same display.

That 'new application' needs to also have android:resizeableActivity="true" in the manifest. True is the default, but I specified to just be explicit and protect future framework changes.

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:resizeableActivity="true"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
Todd DeLand
  • 3,065
  • 1
  • 26
  • 15
  • 1
    Thanks for the update Todd :), Though FYI, since I posted this, Samsung has introduced Samsung DeX, and when running on a device with DeX support display 1 is not the external display, I assume that it is some virtual display for offscreen rendering, so display 2 is the external display, so please bare this in mind when developing for multi-screen. – Smiler Feb 06 '19 at 15:27
  • 1
    Also, as this thread will likely attract alot more views soon as Android Q brings desktop mode to AOSP, I should note that things may change in the new Android desktop framework so please do a little more research before commiting to the code that me and Todd have provided. Good luck with your multi-screen efforts :) – Smiler Feb 06 '19 at 15:34
  • setLaunchDisplayId() is not possible below Androoid 8. Is there any alternatives? – c-an Nov 09 '20 at 02:25
  • @c-an I think you are out of luck. Multi-display support was not introduced until Android 8.0: https://developer.android.com/about/versions/oreo/android-8.0#mds – JacquesBauer Feb 09 '21 at 20:23
  • @JacquesBauer, the device is updated and now it's 9.0. But I found out that this doesn't offer interaction between two displays.. Do you have any suggestions? I don't want to use Presentation class because it can't use keyboard on it. – c-an Jun 01 '21 at 08:25
0

each time you add a new simulate screen the display id changes. it resets to 1 when you restart. check if this is the issue. adb command that you specified doesnt seem to work as you said.