-
Notifications
You must be signed in to change notification settings - Fork 25.2k
Add local network permission prompt on android 17 #57291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| /* | ||
| * Copyright (c) Meta Platforms, Inc. and affiliates. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
|
|
||
| package com.facebook.react.devsupport | ||
|
|
||
| import android.app.Activity | ||
| import android.content.pm.PackageManager | ||
| import com.facebook.react.common.build.ReactBuildConfig | ||
| import com.facebook.react.modules.core.PermissionAwareActivity | ||
| import com.facebook.react.util.AndroidVersion | ||
|
|
||
| /** | ||
| * Debug-only helper to request the runtime `ACCESS_LOCAL_NETWORK` permission needed to reach Metro | ||
| * on Android 17 (SDK 37) devices, which gate local-network addresses (the emulator's `10.0.2.2` | ||
| * alias, a device's Wi-Fi/LAN IP). Requested only in debuggable builds, and always (like iOS), since | ||
| * the dev-server host can change at runtime (e.g. switching from `adb reverse` to a LAN IP). | ||
| */ | ||
| internal object LocalNetworkPermissionUtil { | ||
| private const val PERMISSION = "android.permission.ACCESS_LOCAL_NETWORK" | ||
| private const val PERMISSION_REQUEST_CODE = 1 | ||
|
|
||
| /** | ||
| * Invokes [onResolved] once it is safe to connect to Metro: immediately when no permission is | ||
| * needed, or after the user answers the `ACCESS_LOCAL_NETWORK` prompt otherwise. | ||
| */ | ||
| @JvmStatic | ||
| fun requestLocalNetworkAccessIfNeeded(activity: Activity, onResolved: Runnable) { | ||
| if (activity is PermissionAwareActivity && needsLocalNetworkPrompt(activity)) { | ||
| activity.requestPermissions(arrayOf(PERMISSION), PERMISSION_REQUEST_CODE) { _, _, _ -> | ||
| onResolved.run() | ||
| true | ||
| } | ||
| } else { | ||
| onResolved.run() | ||
| } | ||
| } | ||
|
|
||
| /** Whether the `ACCESS_LOCAL_NETWORK` prompt must be shown before reaching the dev server. */ | ||
| private fun needsLocalNetworkPrompt(activity: Activity): Boolean { | ||
| if (!ReactBuildConfig.DEBUG) return false // dev-server only; never prompt in release builds | ||
| if (!AndroidVersion.isAtLeastSdk37()) return false // enforced by the device, not app targetSdk | ||
| return activity.checkSelfPermission(PERMISSION) != PackageManager.PERMISSION_GRANTED | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,13 @@ internal object AndroidVersion { | |
| */ | ||
| internal const val VERSION_CODE_BAKLAVA: Int = 36 | ||
|
|
||
| /** | ||
| * This is the version code for Android 17 (SDK Level 37). Internally at Meta this code is also | ||
| * compiled against SDK 34, so we need to retain this constant instead of using | ||
| * [Build.VERSION_CODES.CINNAMON_BUN] directly. | ||
| */ | ||
| internal const val VERSION_CODE_CINNAMON_BUN: Int = 37 | ||
|
|
||
| /** | ||
| * android.R.attr.windowOptOutEdgeToEdgeEnforcement added in API 35. Internally at Meta this code | ||
| * is compiled against an SDK that may not have this attribute defined. | ||
|
|
@@ -51,4 +58,13 @@ internal object AndroidVersion { | |
| fun isAtLeastTargetSdk36(context: Context): Boolean = | ||
| Build.VERSION.SDK_INT >= VERSION_CODE_BAKLAVA && | ||
| context.applicationInfo.targetSdkVersion >= VERSION_CODE_BAKLAVA | ||
|
|
||
| /** | ||
| * This method is used to check if the current device is running Android 17 (SDK Level 37) or | ||
| * higher. Unlike the `isAtLeastTargetSdk*` helpers, this checks the device API level only and not | ||
| * the app's targetSdk, because Android 17 gates the local-network runtime permission for any app | ||
| * that declares it, regardless of targetSdk. | ||
| */ | ||
| @JvmStatic | ||
| internal fun isAtLeastSdk37(): Boolean = Build.VERSION.SDK_INT >= VERSION_CODE_CINNAMON_BUN | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the permission can only be requested if
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's required on any device running android 17 regardless of the target level |
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.