0

I'm trying to launch a second activity on a secondary display. This works fine on the emulators, but I need the secondary display to handle touch events.

With Android Pie, launching an activity on some second displays would throw a security exception. Google recently pushed out this new API for Android Q - isActivityStartAllowedOnDisplay() (https://developer.android.com/reference/android/app/ActivityManager.html#isActivityStartAllowedOnDisplay(android.content.Context,%2520int,%2520android.content.Intent)) - to be able to tell if the second display has this security exception or not.

This new API is helpful, BUT, is there any way around it? Maybe I've misunderstood the documentation, but it seems like if the device doesn't support it, then there's no way around it. Does anyone know of any displays that will NOT throw this security exception?

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Karringgton
  • 207
  • 1
  • 3
  • 11
  • 2
    "I need the secondary display to handle touch events" -- I am not aware that Android supports this. "Does anyone know of any displays that will NOT throw this security exception?" -- I have never had that exception get thrown in my testing. I test with LCD monitors and projectors, connected to the Android device via HDMI adapters. "With Android Pie, launching an activity on some second displays would throw a security exception" -- which ones? I might pick up one for some testing. – CommonsWare Jun 06 '19 at 16:35
  • 1
    For some context, this CAN be done on CUSTOM hardware as long as you override specific configurations. This is supported in Android starting in Android O but not with any "off the shelf" devices. This was confirmed at the 2019 Google Automotive Bootcamp by a Googler. – Karringgton Jun 26 '19 at 18:12
  • 1
    I also want to add that this can be done with off the shelf devices if you make some custom changes to AOSP and flash that to the device. – Karringgton Jul 23 '19 at 23:21

1 Answers1

1

In order to get touch events to register on the secondary display (GeChic Touch Monitor), I had a DisplayLink device connected between the Android device and touch display. At this point, it was mirroring the view on the phone/tablet but would handle touch events. So, I wrote an app that would attempt to launch a second activity on the second display using this code on Android Pie OS:

DisplayManager mgr = (DisplayManager) this.getBaseContext().getSystemService(Context.DISPLAY_SERVICE);

if (mgr != null) {
    Display[] displays = mgr.getDisplays();

    for (int i = 0; i < displays.length; i++) {
        Display display = displays[i];
        Point point = new Point();
        display.getSize(point);

        if (point.y == PX_HEIGHT_OF_SECONDARY_DISPLAY || point.x == PX_HEIGHT_OF_SECONDARY_DISPLAY) {
            Context displayContext = createDisplayContext(display);
            Intent newIntent = new Intent(displayContext, ActivityCID.class);

            ActivityOptions options = ActivityOptions.makeBasic();
            options.setLaunchDisplayId(display.getDisplayId());
            newIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(newIntent, options.toBundle());
            return;
        }
    }
}

Note that I did not use display.getDisplayId() and did a hacky way with the point.y and point.x values with a pixel width or height that did not match the pixel width or height of the Android phone/tablet. The displayId() was not always a consistent value which "should" be stable in Android Q. This is where the app would crash and the second activity would fail with a security permissions error. So, I used Android Q Beta to test the new isActivityStartAllowedOnDisplay() API. I ran this through Android Studio onto the phone (which was on Android Q Beta OS) to run it and to no surprise, the secondary display came back false. See code below:

public void launchOnSecondaryDisplay(Display display) {

    Context displayContext = createDisplayContext(display);
    Intent newIntent = new Intent(displayContext, ActivityTest.class);

    ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Activity.ACTIVITY_SERVICE);
        if (activityManager != null) {
            boolean allowsDisplay = activityManager.isActivityStartAllowedOnDisplay(displayContext, display.getDisplayId(), newIntent);

            if (allowsDisplay) {
                ActivityOptions options = ActivityOptions.makeBasic();
                options.setLaunchDisplayId(display.getDisplayId());
                newIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(newIntent, options.toBundle());
            } else {
                Toast.makeText(this, "Cannot start activity on that display as it is not supported.", Toast.LENGTH_LONG).show();
            }

        }
    }

I decided to try this through the command line. After networking the physical device to match my Mac's connected network, I was able to connect to the phone wirelessly and was able to make changes in adb. Using an adb command, I was able to get a secondary activity on the secondary display! It seemed to be working! But no, it was not... Touch events still continued to act like the device was being mirrored so this was still a problem and was not going to work.

I discussed this with the Googler as well and was explained that adb root can override these permissions. However, there was still no way to get the touch events to map to the second activity on the secondary display.

At the moment of writing this, the only supported way to test multi touch displays is to use a physical device running Android Q Beta and follow these steps:

  1. enable developer options,
  2. in developer options, enable these 4 options: Force All Activities to be Resizeable, Freeform Windows, Force Desktop, and Simulate Secondary Display (doesn't matter which option picked for simulate secondary display),
  3. reboot the device,
  4. connect a mouse to the device. The mouse will show up and be stuck inside the overlaying window that is "simulating the secondary display". This will handle touch events.

In the future, there will be emulators that have multiple displays to better test multi display applications but this is not available at the moment.

Karringgton
  • 207
  • 1
  • 3
  • 11