Skip to content
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

android: Update targetSdkVersion to 34, i.e., Android 14 #5892

Merged
merged 3 commits into from
Sep 28, 2024

Conversation

chrisbobbe
Copy link
Contributor

With a prep commit that came from @gnprice's investigation into some code in react-native that needed to change; thanks Greg for that!

Fixes: #5877

@chrisbobbe
Copy link
Contributor Author

Greg, when you have some time to do so, could you test this on your device running Android 14?

Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks for taking care of this!

The changes look good. I'll test when I'm at home (since I discovered the other day at #5891 (comment) that I no longer have a working zulip-mobile environment on my office desktop).

+ */
+ private void compatRegisterReceiver(
+ Context context, BroadcastReceiver receiver, IntentFilter filter, boolean exported) {
+ if (Build.VERSION.SDK_INT >= 34 && context.getApplicationInfo().targetSdkVersion >= 34) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure this targetSdkVersion check shouldn't be here and is just cruft that makes the code more complicated to think about. But 🤷 React Native's code quality is rapidly becoming not our problem — and definitely the right thing here is to backport the commit verbatim, like this. (So long as it doesn't have bugs with direct behavior impact, anyway.)

@gnprice
Copy link
Member

gnprice commented Sep 20, 2024

Oh, do you have these changes as a branch in a react-native Git repo? It'd be good to (a) push that branch to our fork zulip/react-native, and (b) mention the branch name and commit ID here, in the commit that updates the patch.

@chrisbobbe
Copy link
Contributor Author

chrisbobbe commented Sep 20, 2024

Oh, do you have these changes as a branch in a react-native Git repo? It'd be good to (a) push that branch to our fork zulip/react-native, and (b) mention the branch name and commit ID here, in the commit that updates the patch.

I don't, but I'll create such a branch and do those things.

@chrisbobbe chrisbobbe force-pushed the pr-target-sdk-version-34 branch from c8f801d to 5a4e92e Compare September 21, 2024 01:46
@chrisbobbe
Copy link
Contributor Author

Done; revision pushed.

@gnprice
Copy link
Member

gnprice commented Sep 24, 2024

Thanks!

I just tried this version with tools/run-android on my Android 14 device (a Pixel 8). It still crashes on startup, with the same stack trace as at #5877 (comment) .

I looked at the Java source file that's supposed to be patched, and it has the patch:

$ grep -C2 compatRegister node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java
        IntentFilter filter = new IntentFilter();
        filter.addAction(getReloadAppAction(mApplicationContext));
        compatRegisterReceiver(mApplicationContext, mReloadAppBroadcastReceiver, filter, true);
        mIsReceiverRegistered = true;
      }
--
   * <p>https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported
   */
  private void compatRegisterReceiver(
      Context context, BroadcastReceiver receiver, IntentFilter filter, boolean exported) {
    if (Build.VERSION.SDK_INT >= 34 && context.getApplicationInfo().targetSdkVersion >= 34) {

I suspect what's happening is that the build of the Android side is using a published binary artifact for the 0.68.7 release, not the source code in node_modules/. That's the reason for the Gradle-related steps described here:
https://github.com/zulip/zulip-mobile/blob/main/docs/howto/rn-from-git.md#per-project-setup

So I think those steps will still be necessary.

The other two changes we currently have in this file are in JS code (for tests only, in fact) and in a build-time script for the iOS build. That's why they didn't need those changes.

When I read this PR on Friday, I looked in the history and saw our previous use of patch-package for react-native, at b546b07, which is in native code that I expect is part of that same build. So that caused me to think that maybe things had changed since I last studied how this aspect of the build worked, and those setup changes weren't needed.

But looking again now, I see from the commit message that the problem it was meant to solve was only in a build with Xcode, for iOS. Those have always built from source, rather than using a published build artifact like the Android build. So I think the story must be that that patch never did have an effect on Android — and that just was fine, because the problem it was solving didn't exist there.

@chrisbobbe
Copy link
Contributor Author

chrisbobbe commented Sep 24, 2024

I see. So, more work to do here.

In step 4 of that doc:

  1. Follow the various steps in this
    doc

    that involve tweaking several Gradle files located under android/ in
    the app. Commit the result.

I followed that link and added the includeBuild lines it says to add:

  // ...
  include ':app'
  includeBuild('../node_modules/@react-native/gradle-plugin')
  
+ includeBuild('../node_modules/react-native') {
+     dependencySubstitution {
+         substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid"))
+         substitute(module("com.facebook.react:react-native")).using(project(":packages:react-native:ReactAndroid"))
+         substitute(module("com.facebook.react:hermes-android")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
+         substitute(module("com.facebook.react:hermes-engine")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
+     }
+ }

But that caused a build failure:

$ tools/gradle :app:assembleDebug

FAILURE: Build failed with an exception.

* Where:
Settings file '/Users/chrisbobbe/dev/zulip-mobile/android/settings.gradle' line: 13

* What went wrong:
Project with path ':packages:react-native:ReactAndroid' not found in build 'react-native'.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s

That docs website has been updated a few times, and I think we'll need to follow an older version of these instructions.

I tried the next-to-latest version, before facebook/react-native-website@22da0cc63 "Update how-to-build-from-source for 0.72+". That failed with Project with path ':ReactAndroid' not found in build 'react-native'..

So I think the next thing for me to try is the version just before facebook/react-native-website@50a01ac0d 'Update the "Build from source" page'. Those instructions are much more complicated, though, so I'd like to check in before I get started. Does that seem like the right next step? Thanks in advance :)

@gnprice
Copy link
Member

gnprice commented Sep 24, 2024

So I think the next thing for me to try […] Does that seem like the right next step?

Let's move to a chat thread for that discussion:
https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/RN.20from.20Git/near/1948101

chrisbobbe added a commit to chrisbobbe/react-native that referenced this pull request Sep 27, 2024
The Java changes in a recent commit won't be picked up in
zulip-mobile unless we build React Native from source; discussion:
  zulip/zulip-mobile#5892 (comment)

After those Java changes, though, some new constants are read
(`Context.RECEIVER_EXPORTED` and `Context.RECEIVER_NOT_EXPORTED`),
and to get those, we need compileSdkVersioin >= 34.
chrisbobbe added a commit to chrisbobbe/react-native that referenced this pull request Sep 27, 2024
The Java changes in a recent commit won't be picked up in
zulip-mobile unless we build React Native from source; discussion:
  zulip/zulip-mobile#5892 (comment)

After those Java changes, though, some new constants are read
(`Context.RECEIVER_EXPORTED` and `Context.RECEIVER_NOT_EXPORTED`).
To get those, we need compileSdkVersion >= 34.
@chrisbobbe chrisbobbe force-pushed the pr-target-sdk-version-34 branch from 5a4e92e to 8ffc4d2 Compare September 27, 2024 23:10
@chrisbobbe
Copy link
Contributor Author

Thanks for all your help on this, @gnprice! Revision pushed.

@chrisbobbe chrisbobbe force-pushed the pr-target-sdk-version-34 branch from 8ffc4d2 to 9a47747 Compare September 27, 2024 23:56
@chrisbobbe
Copy link
Contributor Author

OK, added a commit to let Gradle use more memory; that should help with the CI failure (which was showing out-of-memory errors).

@gnprice
Copy link
Member

gnprice commented Sep 28, 2024

Great, glad to see this working!

The changes all look good. And I just tested making a debug build on my laptop and running it on my Android 14 device, and it seems to run fine. Merging now.

With the upcoming change to build RN from source, CI was failing
with out-of-memory errors. This should help with those.

Why twice as much memory? See 3677788, which bumped this value
from 1024 to 1280. From the commit message there:

  Compare facebook/react-native@a2a703247, which happened on the way
  to RN v0.68.  That one had the explanation

    > Updates maximum heap size for the gradle build to account for
    > building RN from source when new architecture is enabled.

  which doesn't apply as we aren't yet adopting RN's New
  Architecture. But perhaps if we did, we'd need to increase the
  heap size even more: that commit takes it to 2 GiB.

We're not adopting RN's New Architecture, and we don't plan to in
this legacy codebase. But we will be building RN from source, so
this seems like a good value to try.
This gets us zulip/react-native@5c36f102f and its fixup commit
zulip/react-native@b7b2f6c22 (on the `0.68.7-zulip` branch), to fix
a build failure with `targetSdkVersion = 34` without having to
upgrade to RN v0.73. (The build failure is in debug builds only, but
we still need to make those to develop fixes in this legacy project
as needed.)

Thanks to Greg for investigating the build failure:
  zulip#5877 (comment)

Since (as part of working on this) the `0.68.7-zulip` branch also
includes the things that were in the patch-package patch, that patch
becomes redundant and we delete it here.

Done by digesting the history of RN's doc on building RN from
source:
  facebook/react-native-website@22da0cc63
and making some simplifications.

The line `ndkVersion = 24…` sets a variable that ReactAndroid reads,
to control the NDK version it builds with. It would otherwise build
with NDK 21, which is old and chosen automatically based on
ReactAndroid's targetSdkVersion of 31. We need it to be at least 24
for Apple Silicon support.
This change will be required in order to upload new releases to the
Play Store, effective 2024-10-31, which includes the extension we
requested.

This change causes Android 14 and later to apply to our app a number
of behavior changes introduced in that version, documented here:
  https://developer.android.com/about/versions/14/behavior-changes-14

Fixes: zulip#5877
@gnprice gnprice force-pushed the pr-target-sdk-version-34 branch from 9a47747 to fb6ea0f Compare September 28, 2024 00:49
@gnprice gnprice merged commit fb6ea0f into zulip:main Sep 28, 2024
1 check failed
@chrisbobbe chrisbobbe deleted the pr-target-sdk-version-34 branch September 28, 2024 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Target Android 14 (set targetSdkVersion to 34), by 2024-10 deadline
2 participants