Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions packages/react-native/ReactAndroid/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -584,11 +584,9 @@ android {
minSdk = libs.versions.minSdk.get().toInt()

aarMetadata {
// RN's public ABI exposes no android API newer than 34, and the source is written to
// compile against SDK 34 (see util/AndroidVersion.kt). compileSdk is 36 only to build
// against the latest platform — it is not an API requirement. Without this, AGP 9
// defaults minCompileSdk to compileSdk (36), needlessly forcing every consuming
// library/app to compileSdk 36.
// RN's public ABI exposes no Android API newer than 34, so consumers do not need to
// match ReactAndroid's compile SDK. Without this, AGP 9 defaults minCompileSdk to
// compileSdk, needlessly forcing every consuming library/app to use the same SDK.
minCompileSdk = 34
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,48 +14,18 @@ import android.os.Build
internal object AndroidVersion {

/**
* This is the version code for Android 15 (SDK Level 35). Internally at Meta this code is also
* compiled against SDK 34, so we need to retain this constant instead of using
* [Build.VERSION_CODES.VANILLA_ICE_CREAM] directly.
*/
internal const val VERSION_CODE_VANILLA_ICE_CREAM: Int = 35

/**
* This is the version code for Android 16 (SDK Level 36). Internally at Meta this code is also
* compiled against SDK 34, so we need to retain this constant instead of using
* [Build.VERSION_CODES.BAKLAVA] directly.
*/
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
* This is the version code for Android 17 (SDK Level 37). Internally at Meta this code is
* compiled against SDK 36, 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.
* https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/res/res/values/public-final.xml;l=3848
*/
internal const val ATTR_WINDOW_OPT_OUT_EDGE_TO_EDGE_ENFORCEMENT: Int = 0x0101069a

/**
* This method is used to check if the current device is running Android 15 (SDK Level 35) or
* higher and the app is targeting Android 15 (SDK Level 35) or higher.
*/
@JvmStatic
internal fun isAtLeastTargetSdk35(context: Context): Boolean =
Build.VERSION.SDK_INT >= VERSION_CODE_VANILLA_ICE_CREAM &&
context.applicationInfo.targetSdkVersion >= VERSION_CODE_VANILLA_ICE_CREAM

/**
* This method is used to check if the current device is running Android 16 (SDK Level 36) or
* higher and the app is targeting Android 16 (SDK Level 36) or higher.
*/
@JvmStatic
fun isAtLeastTargetSdk36(context: Context): Boolean =
Build.VERSION.SDK_INT >= VERSION_CODE_BAKLAVA &&
context.applicationInfo.targetSdkVersion >= VERSION_CODE_BAKLAVA
Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA &&
context.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.BAKLAVA
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.view.AccessibilityDelegateCompat;
Expand All @@ -47,12 +46,10 @@
import com.facebook.react.uimanager.style.BorderStyle;
import com.facebook.react.uimanager.style.LogicalEdge;
import com.facebook.react.uimanager.style.Overflow;
import com.facebook.react.util.AndroidVersion;
import com.facebook.react.views.text.internal.span.CanvasEffectSpan;
import com.facebook.react.views.text.internal.span.ReactFragmentIndexSpan;
import com.facebook.react.views.text.internal.span.ReactTagSpan;
import com.facebook.yoga.YogaMeasureMode;
import java.lang.reflect.Method;

@Nullsafe(Nullsafe.Mode.LOCAL)
public class ReactTextView extends AppCompatTextView implements ReactCompoundView {
Expand All @@ -63,10 +60,6 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
// https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/widget/TextView.java#L854
private static final int DEFAULT_GRAVITY = Gravity.TOP | Gravity.START;

// TextView.setUseBoundsForWidth (API 35+). Looked up reflectively because some internal targets
// compile against an SDK older than 35 (see AndroidVersion).
private static final @Nullable Method SET_USE_BOUNDS_FOR_WIDTH = resolveSetUseBoundsForWidth();

private int mNumberOfLines;
private @Nullable TextUtils.TruncateAt mEllipsizeLocation;
private boolean mAdjustsFontSizeToFit;
Expand All @@ -87,17 +80,6 @@ public ReactTextView(Context context) {
initView();
}

private static @Nullable Method resolveSetUseBoundsForWidth() {
if (Build.VERSION.SDK_INT < AndroidVersion.VERSION_CODE_VANILLA_ICE_CREAM) {
return null;
}
try {
return TextView.class.getMethod("setUseBoundsForWidth", boolean.class);
} catch (NoSuchMethodException e) {
return null;
}
}

/**
* Keeps this view's line breaking on the same basis as TextLayoutManager's measurement.
*
Expand All @@ -109,13 +91,8 @@ public ReactTextView(Context context) {
* one.
*/
private void matchLineBreakingToMeasurement() {
if (SET_USE_BOUNDS_FOR_WIDTH == null) {
return;
}
try {
SET_USE_BOUNDS_FOR_WIDTH.invoke(this, false);
} catch (ReflectiveOperationException e) {
FLog.w(ReactConstants.TAG, "Could not disable useBoundsForWidth on ReactTextView", e);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
setUseBoundsForWidth(false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,15 @@ public fun setEdgeToEdgeFeatureFlagOn() {
internal fun updateEdgeToEdgeFeatureFlag(activity: Activity) {
// When the app targets SDK 35+, edge-to-edge may be enforced by the OS even if the
// feature flag wasn't explicitly set. In that case, turn the flag on to match.
if (AndroidVersion.isAtLeastTargetSdk35(activity)) {
if (Build.VERSION.SDK_INT >= AndroidVersion.VERSION_CODE_BAKLAVA) {
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM &&
activity.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.VANILLA_ICE_CREAM
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) {
// The device is running Android 16+ (where edge-to-edge is always enforced)
isEdgeToEdgeFeatureFlagOn = true
} else {
val attributes = intArrayOf(AndroidVersion.ATTR_WINDOW_OPT_OUT_EDGE_TO_EDGE_ENFORCEMENT)
val attributes = intArrayOf(android.R.attr.windowOptOutEdgeToEdgeEnforcement)
val typedArray = activity.theme.obtainStyledAttributes(attributes)

// The device is running Android 15 with / without opting out
Expand Down
Loading