From 891f0f31ddc01a27b6589a56482c8fa522ac16c9 Mon Sep 17 00:00:00 2001 From: Thomas FETIVEAU Date: Fri, 23 Jun 2023 12:57:49 +0200 Subject: [PATCH 1/6] feat(arch): support both new arch and old arch on Android --- NativeRNExitApp.ts | 8 +++ RNExitApp.podspec | 17 ++++++ android/build.gradle | 20 ++++++- .../github/wumke/RNExitApp/RNExitAppImpl.java | 24 ++++++++ .../wumke/RNExitApp/RNExitAppModule.java | 39 ------------- .../wumke/RNExitApp/RNExitAppPackage.java | 58 ++++++++++--------- android/src/newarch/RNExitApp.java | 28 +++++++++ android/src/oldarch/RNExitApp.java | 27 +++++++++ index.js | 4 +- package.json | 10 +++- 10 files changed, 165 insertions(+), 70 deletions(-) create mode 100644 NativeRNExitApp.ts create mode 100644 android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java delete mode 100644 android/src/main/java/com/github/wumke/RNExitApp/RNExitAppModule.java create mode 100644 android/src/newarch/RNExitApp.java create mode 100644 android/src/oldarch/RNExitApp.java diff --git a/NativeRNExitApp.ts b/NativeRNExitApp.ts new file mode 100644 index 0000000..15d4027 --- /dev/null +++ b/NativeRNExitApp.ts @@ -0,0 +1,8 @@ +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + exitApp: () => void; +} + +export default TurboModuleRegistry.getEnforcing('RNExitApp'); \ No newline at end of file diff --git a/RNExitApp.podspec b/RNExitApp.podspec index 7fa7aa1..1bef843 100644 --- a/RNExitApp.podspec +++ b/RNExitApp.podspec @@ -23,4 +23,21 @@ Pod::Spec.new do |s| s.source_files = 'ios/RNExitApp/**/*.{h,m}' s.dependency 'React-Core' + + # Don't install the dependencies when we run `pod install` in the old architecture. + if ENV["RCT_NEW_ARCH_ENABLED"] == "1" + s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", + "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + } + + s.dependency "React-Codegen" + s.dependency "React-RCTFabric" + s.dependency "RCT-Folly" + s.dependency "RCTRequired" + s.dependency "RCTTypeSafety" + s.dependency "ReactCommon/turbomodule/core" + end end diff --git a/android/build.gradle b/android/build.gradle index c45bdd7..b8cea50 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -19,7 +19,14 @@ def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } +def isNewArchitectureEnabled() { + return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" +} + apply plugin: 'com.android.library' +if (isNewArchitectureEnabled()) { + apply plugin: 'com.facebook.react' +} android { compileSdkVersion safeExtGet('compileSdkVersion', 23) @@ -28,8 +35,7 @@ android { defaultConfig { minSdkVersion safeExtGet('minSdkVersion',16) targetSdkVersion safeExtGet('targetSdkVersion',22) - versionCode 2 - versionName "1.1" + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() ndk { abiFilters "armeabi-v7a", "x86" } @@ -37,6 +43,16 @@ android { lintOptions { warning 'InvalidPackage' } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += ['src/newarch'] + } else { + java.srcDirs += ['src/oldarch'] + } + } + } } dependencies { diff --git a/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java b/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java new file mode 100644 index 0000000..36e2fc7 --- /dev/null +++ b/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java @@ -0,0 +1,24 @@ +package com.github.wumke.RNExitApp; + +import android.app.AlarmManager; +import android.content.Context; + +import com.facebook.react.bridge.ReactApplicationContext; + +class RNExitAppImpl { + + public static final String NAME = "RNExitApp"; + + ReactApplicationContext RCTContext; + + AlarmManager alarmManager; + + public RNExitAppImpl(ReactApplicationContext reactContext) { + RCTContext = reactContext; + alarmManager = (AlarmManager) reactContext.getSystemService(Context.ALARM_SERVICE); + } + + public void exitApp() { + android.os.Process.killProcess(android.os.Process.myPid()); + } +} diff --git a/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppModule.java b/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppModule.java deleted file mode 100644 index c6d6299..0000000 --- a/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppModule.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.github.wumke.RNExitApp; - -import android.app.AlarmManager; -import android.app.Application; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.util.Log; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; - -public class RNExitAppModule extends ReactContextBaseJavaModule { - - ReactApplicationContext reactContext; - AlarmManager alarmManager; - - public RNExitAppModule(ReactApplicationContext reactContext) { - super(reactContext); - this.reactContext = reactContext; - alarmManager = (AlarmManager) reactContext.getSystemService(Context.ALARM_SERVICE); - } - - @Override - public String getName() { - return "RNExitApp"; - } - - @ReactMethod - public void exitApp() { - android.os.Process.killProcess(android.os.Process.myPid()); - } -} diff --git a/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppPackage.java b/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppPackage.java index 335df3b..d8c256d 100644 --- a/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppPackage.java +++ b/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppPackage.java @@ -1,39 +1,45 @@ package com.github.wumke.RNExitApp; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import androidx.annotation.Nullable; -import com.facebook.react.ReactPackage; +import com.facebook.react.TurboReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; -import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; -public class RNExitAppPackage implements ReactPackage { +import java.util.HashMap; +import java.util.Map; - @Override - public List createNativeModules( - ReactApplicationContext reactContext) { - List modules = new ArrayList<>(); - - modules.add(new RNExitAppModule(reactContext)); - - return modules; - } +public class RNExitAppPackage extends TurboReactPackage { - // override removed to be compatible with rn0.47+ - //@Override - public List> createJSModules() { - - return Collections.emptyList(); + @Nullable + @Override + public NativeModule getModule(String name, ReactApplicationContext reactContext) { + if (name.equals(RNExitAppImpl.NAME)) { + return new RNExitApp(reactContext); + } else { + return null; + } } @Override - public List createViewManagers( - ReactApplicationContext reactContext) { - return Collections.emptyList(); + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return () -> { + final Map moduleInfos = new HashMap<>(); + boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + moduleInfos.put( + RNExitAppImpl.NAME, + new ReactModuleInfo( + RNExitAppImpl.NAME, + RNExitAppImpl.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + false, // hasConstants + false, // isCxxModule + isTurboModule // isTurboModule + )); + return moduleInfos; + }; } - } diff --git a/android/src/newarch/RNExitApp.java b/android/src/newarch/RNExitApp.java new file mode 100644 index 0000000..deebace --- /dev/null +++ b/android/src/newarch/RNExitApp.java @@ -0,0 +1,28 @@ +package com.github.wumke.RNExitApp; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.ReactApplicationContext; + +import com.github.wumke.RNExitApp.NativeRNExitAppSpec; + +public class RNExitApp extends NativeRNExitAppSpec { + + private final RNExitAppImpl delegate; + + public RNExitApp(ReactApplicationContext reactContext) { + super(reactContext); + delegate = new RNExitAppImpl(reactContext); + } + + @NonNull + @Override + public String getName() { + return RNExitAppImpl.NAME; + } + + @Override + public void exitApp() { + delegate.exitApp(); + } +} diff --git a/android/src/oldarch/RNExitApp.java b/android/src/oldarch/RNExitApp.java new file mode 100644 index 0000000..9d8a9d1 --- /dev/null +++ b/android/src/oldarch/RNExitApp.java @@ -0,0 +1,27 @@ +package com.github.wumke.RNExitApp; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; + +import android.util.Log; + +public class RNExitApp extends ReactContextBaseJavaModule { + + private final RNExitAppImpl delegate; + + public RNExitApp(ReactApplicationContext reactContext) { + super(reactContext); + delegate = new RNExitAppImpl(reactContext); + } + + @Override + public String getName() { + return RNExitAppImpl.NAME; + } + + @ReactMethod + public void exitApp() { + delegate.exitApp(); + } +} diff --git a/index.js b/index.js index 3ea1fff..c45db97 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,8 @@ -import {NativeModules} from 'react-native'; +import NativeRNExitApp from "./NativeRNExitApp"; var RNExitApp = { exitApp: function() { - NativeModules.RNExitApp.exitApp(); + NativeRNExitApp.exitApp(); } }; diff --git a/package.json b/package.json index d3db023..ec4ac7a 100644 --- a/package.json +++ b/package.json @@ -26,5 +26,13 @@ "bugs": { "url": "https://github.com/wumke/react-native-exit-app/issues" }, - "homepage": "http://watchwimswork.be" + "homepage": "http://watchwimswork.be", + "codegenConfig": { + "name": "RNExitApp", + "type": "modules", + "jsSrcsDir": ".", + "android": { + "javaPackageName": "com.github.wumke.RNExitApp" + } + } } From baac7afb7d5e01456534b0b8ac2e204feff1383a Mon Sep 17 00:00:00 2001 From: Thomas FETIVEAU Date: Fri, 23 Jun 2023 14:08:28 +0200 Subject: [PATCH 2/6] feat(arch) support both new and old arch on iOS --- RNExitApp.podspec | 4 ++-- ios/RNExitApp/RNExitApp.h | 19 +++++++++++++++++++ ios/RNExitApp/RNExitApp.m | 17 ----------------- ios/RNExitApp/RNExitApp.mm | 30 ++++++++++++++++++++++++++++++ package.json | 2 +- 5 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 ios/RNExitApp/RNExitApp.h delete mode 100644 ios/RNExitApp/RNExitApp.m create mode 100644 ios/RNExitApp/RNExitApp.mm diff --git a/RNExitApp.podspec b/RNExitApp.podspec index 1bef843..d08535c 100644 --- a/RNExitApp.podspec +++ b/RNExitApp.podspec @@ -20,13 +20,13 @@ Pod::Spec.new do |s| s.source = { :git => repository, :tag => version } s.platforms = { :ios => "9.0", :tvos => "11.0" } s.preserve_paths = 'README.md', 'package.json', '*.js' - s.source_files = 'ios/RNExitApp/**/*.{h,m}' + s.source_files = 'ios/RNExitApp/**/*.{h,m,mm}' s.dependency 'React-Core' # Don't install the dependencies when we run `pod install` in the old architecture. if ENV["RCT_NEW_ARCH_ENABLED"] == "1" - s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" + s.compiler_flags = folly_flags + " -DRCT_NEW_ARCH_ENABLED=1" s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", diff --git a/ios/RNExitApp/RNExitApp.h b/ios/RNExitApp/RNExitApp.h new file mode 100644 index 0000000..3d7124c --- /dev/null +++ b/ios/RNExitApp/RNExitApp.h @@ -0,0 +1,19 @@ +#if __has_include() +#import +#elif __has_include("RCTBridgeModule.h") +#import "RCTBridgeModule.h" +#else +#import "React/RCTBridgeModule.h" +#endif + +#if RCT_NEW_ARCH_ENABLED +#import +#endif + +@interface RNExitApp : NSObject +@end + +#if RCT_NEW_ARCH_ENABLED +@interface RNExitApp () +@end +#endif diff --git a/ios/RNExitApp/RNExitApp.m b/ios/RNExitApp/RNExitApp.m deleted file mode 100644 index 3a61a49..0000000 --- a/ios/RNExitApp/RNExitApp.m +++ /dev/null @@ -1,17 +0,0 @@ -#import -#import - - -@interface RNExitApp : NSObject -@end - -@implementation RNExitApp - -RCT_EXPORT_MODULE(); - -RCT_EXPORT_METHOD(exitApp) -{ - exit(0); -}; - -@end diff --git a/ios/RNExitApp/RNExitApp.mm b/ios/RNExitApp/RNExitApp.mm new file mode 100644 index 0000000..4c9bcd4 --- /dev/null +++ b/ios/RNExitApp/RNExitApp.mm @@ -0,0 +1,30 @@ +#import + +#import "RNExitApp.h" + +#if RCT_NEW_ARCH_ENABLED +#import +#endif + +@implementation RNExitApp + +RCT_EXPORT_MODULE(); + +RCT_EXPORT_METHOD(exitApp) +{ + exit(0); +}; + +# pragma mark - New Architecture + +#if RCT_NEW_ARCH_ENABLED + +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} + +#endif + +@end diff --git a/package.json b/package.json index ec4ac7a..5734cba 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ }, "homepage": "http://watchwimswork.be", "codegenConfig": { - "name": "RNExitApp", + "name": "RNExitAppSpec", "type": "modules", "jsSrcsDir": ".", "android": { From f9083aa07fee8260b4cd62c0de048ef56e841bdc Mon Sep 17 00:00:00 2001 From: Thomas FETIVEAU Date: Fri, 23 Jun 2023 14:11:10 +0200 Subject: [PATCH 3/6] Remove useless android code --- .../main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java b/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java index 36e2fc7..37dbe97 100644 --- a/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java +++ b/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java @@ -1,8 +1,5 @@ package com.github.wumke.RNExitApp; -import android.app.AlarmManager; -import android.content.Context; - import com.facebook.react.bridge.ReactApplicationContext; class RNExitAppImpl { @@ -11,11 +8,8 @@ class RNExitAppImpl { ReactApplicationContext RCTContext; - AlarmManager alarmManager; - public RNExitAppImpl(ReactApplicationContext reactContext) { RCTContext = reactContext; - alarmManager = (AlarmManager) reactContext.getSystemService(Context.ALARM_SERVICE); } public void exitApp() { From 2913b088a3452a6969b5bc0ef9407b2b9af3d471 Mon Sep 17 00:00:00 2001 From: wumke <19737516+wumke@users.noreply.github.com> Date: Tue, 27 Jun 2023 08:37:10 +0200 Subject: [PATCH 4/6] Update package.json replaced old homepage --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5734cba..cbb42dc 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "bugs": { "url": "https://github.com/wumke/react-native-exit-app/issues" }, - "homepage": "http://watchwimswork.be", + "homepage": "https://github.com/wumke/react-native-exit-app", "codegenConfig": { "name": "RNExitAppSpec", "type": "modules", From 0abc26df9b12ce803347b1ea99c8018b5e5b64c5 Mon Sep 17 00:00:00 2001 From: wumke <19737516+wumke@users.noreply.github.com> Date: Tue, 27 Jun 2023 08:44:25 +0200 Subject: [PATCH 5/6] Update package.json Increased major version number, because this is a big change --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cbb42dc..7fd375e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-exit-app", - "version": "1.1.0", + "version": "2.0.0", "description": "Exit,close,kill,shutdown app completely for React Native on iOS and Android.", "main": "index.js", "scripts": { From 233a3ad6be37c89ef5aad12446d257ff9531dd64 Mon Sep 17 00:00:00 2001 From: wumke <19737516+wumke@users.noreply.github.com> Date: Tue, 27 Jun 2023 08:51:31 +0200 Subject: [PATCH 6/6] Update README.md Added notes about v2 --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index d41a496..e6b0ef1 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,16 @@ Exit / Close / Kill / shutdown your react native app. Does not invoke a crash no NOTICE: - for React Native < 0.47 use react-native-exit-app <1.x.x - for React Native > 0.47 use react-native-exit-app >=1.x.x +- React Native with **new architecture** enabled use react-native-exit-app >=2.x.x (**compatible with old architecture**) ## Setup +NOTICE: +Installation steps can be skipped in new architecture and newer React Native versions, just +```bash +npm install react-native-exit-app --save +``` + Fast and easy: ```bash npm install react-native-exit-app --save