4

I am targeting android 12 and using this user association method to make my deep links be handled by app.

I show a dialog with [GO TO SETTINGS] button asking to add supported links from app settings. On [GO TO SETTINGS] click I run this code

val intent = Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
            Uri.parse("package:${context.packageName}"))
        startActivity(context, intent)

Which opens my application [Set as default] section in device settings app, where user can enable supported web addresses. enter image description here

This works for most devices. But for Samsung galaxy s21 (and maybe all Samsungs with android 12) devices application closes without crash log.

I have found out that crash happens in device settings app, here is the log.

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
    at com.android.settings.applications.intentpicker.AppLaunchSettings.onCreate(AppLaunchSettings.java:142)
    at androidx.fragment.app.Fragment.performCreate(Fragment.java:2976)
    at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:475)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:278)
    at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
    at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
    at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3138)
    at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
    at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
    at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:501)
    at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
    at com.samsung.android.settings.core.SecMultiPaneActivity.onStart(SecMultiPaneActivity.java:198)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1455)
    at android.app.Activity.performStart(Activity.java:8307)
    at android.app.ActivityThread.handleStartActivity(ActivityThread.java:4047)
    at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
    at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2425)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:226)
    at android.os.Looper.loop(Looper.java:313)
    at android.app.ActivityThread.main(ActivityThread.java:8582)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:563)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1133)

Is there a way to overcome this? I even can't check this before sending intent, because intent.resolveActivity returns not null result. Thanks for help.

snersesyan
  • 1,647
  • 17
  • 26

2 Answers2

7

It's impossible to open that specific screen on Samsung OneUI 4 / Android 12 devices. It's a bug in Samsung's Settings app. They have to push an OTA system update in order to fix it. I tried dozen of variants, but nothing works, however...

I managed to open this screen ("Apps that can open links" list screen):

screenshot 1

Programatically via android.settings.MANAGE_DOMAIN_URLS:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
{
    if (Build.MANUFACTURER.equalsIgnoreCase("samsung"))
    {
        Intent intent = new Intent();
        intent.setAction("android.settings.MANAGE_DOMAIN_URLS");
        context.startActivity(intent);
    }
    else
    {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS);
        intent.setData(Uri.parse("package:"+context.getPackageName()));
        context.startActivity(intent);
    }
}

You can instruct the user to click on your app from the list. Will navigate here:

screenshot 2

Then instruct the user to navigate to Supported web addresses and check the checkboxes:

screenshot 3

You can detect whether the user has checked the boxes by doing:

private static String getAssociatedDeepLinkingUrlPackageName(@NonNull String url)
{
    Intent resolveIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    ResolveInfo resolveInfo = applicationContext.getPackageManager().resolveActivity(resolveIntent, PackageManager.MATCH_DEFAULT_ONLY);
    return resolveInfo.activityInfo.packageName;
}
if (!getAssociatedDeepLinkingUrlPackageName("https://www.example.com").equals(BuildConfig.APPLICATION_ID))
{
     //tell the user he needs to check the link in the settings app
     //show "go to settings" button, on click navigate to MANAGE_DOMAIN_URLS screen
     //tell the user instructions on what to do on that settings screen
}
RiveN
  • 2,595
  • 11
  • 13
  • 26
user1658358
  • 71
  • 2
  • 3
  • Should we add `try-catch` to the first intent? According to https://stackoverflow.com/questions/26752656/whats-the-meaning-of-new-systemapi-annotation-any-difference-from-hide `"android.settings.MANAGE_DOMAIN_URLS"` is `ACTION_MANAGE_DOMAIN_URLS` which is `@SystemApi`. So I suspect this constant may change. – CoolMind Aug 03 '23 at 09:33
2

Android using custom UI called One UI 4. It not yet update this page, so in Samsung device do not have this page (at this moment).

You can work around by open App Setting page and let user select on "Set as Default" action.

or using

      Intent intent;
      if (manufactorer.contains("samsung")) {
        intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + localContext.getPackageName()));
      } else {
        intent = new Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS, Uri.parse("package:" + localContext.getPackageName()));
      }
Lucas LUU
  • 21
  • 1