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/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 diff --git a/RNExitApp.podspec b/RNExitApp.podspec index 7fa7aa1..d08535c 100644 --- a/RNExitApp.podspec +++ b/RNExitApp.podspec @@ -20,7 +20,24 @@ 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_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..37dbe97 --- /dev/null +++ b/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppImpl.java @@ -0,0 +1,18 @@ +package com.github.wumke.RNExitApp; + +import com.facebook.react.bridge.ReactApplicationContext; + +class RNExitAppImpl { + + public static final String NAME = "RNExitApp"; + + ReactApplicationContext RCTContext; + + public RNExitAppImpl(ReactApplicationContext reactContext) { + RCTContext = reactContext; + } + + 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/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 d3db023..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": { @@ -26,5 +26,13 @@ "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", + "jsSrcsDir": ".", + "android": { + "javaPackageName": "com.github.wumke.RNExitApp" + } + } }