You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android多屏适配:如何在Marshmallow实现ActivityOptions.setLaunchDisplayId(1)?

Hey there! Let's work through your multi-display app launch problem, covering everything from Lollipop up to the latest Android versions. I'll also specifically address the Marshmallow compatibility question you had.

Full Solution: Cross-App Second Screen Launch (API 21+)

Step 1: Fix Flag Compatibility

First, let's correct the flag handling in your existing code. The FLAG_ACTIVITY_LAUNCH_ADJACENT was added in Android Nougat (API 24), so we need to conditionally add it only for supported versions to avoid crashes on older devices:

Intent launchApp = MyApplication.getInstance().getActivity()
    .getPackageManager()
    .getLaunchIntentForPackage(packageInfo.packageName);

// Add mandatory NEW_TASK flag for cross-app launch
launchApp.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

// Add ADJACENT flag only for API 24+ (Nougat and above)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    launchApp.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
}

Step 2: Check for Second Display Existence

Before attempting to launch to a second screen, always verify that the target display (usually ID 1) exists. This prevents errors when no external display is connected:

DisplayManager displayManager = (DisplayManager) MyApplication.getInstance().getActivity()
    .getSystemService(Context.DISPLAY_SERVICE);
Display[] displays = displayManager.getDisplays();
boolean hasSecondDisplay = false;
int targetDisplayId = 1;

for (Display display : displays) {
    if (display.getDisplayId() == targetDisplayId) {
        hasSecondDisplay = true;
        break;
    }
}

if (!hasSecondDisplay) {
    // Fallback: launch on the default display
    MyApplication.getInstance().getActivity().startActivity(launchApp);
    return;
}

Step 3: Version-Specific Launch Logic

Now we'll handle each Android version range with appropriate methods tailored to the system's capabilities:

API 26+ (Oreo and Above)

Use the official public setLaunchDisplayId() method as you already implemented:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    ActivityOptions options = ActivityOptions.makeBasic().setLaunchDisplayId(targetDisplayId);
    MyApplication.getInstance().getActivity().startActivity(launchApp, options.toBundle());
}

API 23-25 (Marshmallow to Nougat)

The setLaunchDisplayId() method exists in these versions but is hidden from the public API. We can use reflection to call it, with a fallback to an intent extra if reflection fails (e.g., on custom ROMs):

else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    try {
        ActivityOptions options = ActivityOptions.makeBasic();
        // Reflect to access the hidden setLaunchDisplayId method
        Method setLaunchDisplayIdMethod = ActivityOptions.class.getMethod("setLaunchDisplayId", int.class);
        setLaunchDisplayIdMethod.invoke(options, targetDisplayId);
        MyApplication.getInstance().getActivity().startActivity(launchApp, options.toBundle());
    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
        // Fallback: use intent extra to specify display ID
        launchApp.putExtra("android.intent.extra.DISPLAY_ID", targetDisplayId);
        MyApplication.getInstance().getActivity().startActivity(launchApp);
    }
}

API 21-22 (Lollipop)

For Lollipop, use the android.intent.extra.DISPLAY_ID intent extra to direct the app to launch on the second display:

else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    launchApp.putExtra("android.intent.extra.DISPLAY_ID", targetDisplayId);
    MyApplication.getInstance().getActivity().startActivity(launchApp);
}

Putting It All Together

Here's the complete combined code that covers all versions from Lollipop to the latest Android release:

// Get launch intent for the target app
Intent launchApp = MyApplication.getInstance().getActivity()
    .getPackageManager()
    .getLaunchIntentForPackage(packageInfo.packageName);

// Set necessary launch flags
launchApp.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    launchApp.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
}

// Verify second display exists
DisplayManager displayManager = (DisplayManager) MyApplication.getInstance().getActivity()
    .getSystemService(Context.DISPLAY_SERVICE);
Display[] displays = displayManager.getDisplays();
boolean hasSecondDisplay = false;
int targetDisplayId = 1;

for (Display display : displays) {
    if (display.getDisplayId() == targetDisplayId) {
        hasSecondDisplay = true;
        break;
    }
}

if (!hasSecondDisplay) {
    MyApplication.getInstance().getActivity().startActivity(launchApp);
    return;
}

// Launch on second screen with version-specific logic
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    ActivityOptions options = ActivityOptions.makeBasic().setLaunchDisplayId(targetDisplayId);
    MyApplication.getInstance().getActivity().startActivity(launchApp, options.toBundle());
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    try {
        ActivityOptions options = ActivityOptions.makeBasic();
        Method setLaunchDisplayIdMethod = ActivityOptions.class.getMethod("setLaunchDisplayId", int.class);
        setLaunchDisplayIdMethod.invoke(options, targetDisplayId);
        MyApplication.getInstance().getActivity().startActivity(launchApp, options.toBundle());
    } catch (Exception e) {
        launchApp.putExtra("android.intent.extra.DISPLAY_ID", targetDisplayId);
        MyApplication.getInstance().getActivity().startActivity(launchApp);
    }
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    launchApp.putExtra("android.intent.extra.DISPLAY_ID", targetDisplayId);
    MyApplication.getInstance().getActivity().startActivity(launchApp);
}

Key Notes for Marshmallow (API 23-25)

  • The setLaunchDisplayId() method is hidden in Marshmallow, so reflection is the only way to access it without relying on unofficial workarounds.
  • Always include a fallback (like the intent extra) to handle edge cases where reflection fails—this is especially important for custom ROMs that may modify hidden system methods.
  • This approach leverages the underlying multi-display functionality already present in Marshmallow while maintaining stability.

内容的提问来源于stack exchange,提问作者Siddu M S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:59:20