From bb52c693b4b4ce66670abe191a455dc164304026 Mon Sep 17 00:00:00 2001 From: Thomas FETIVEAU Date: Tue, 20 Jun 2023 17:13:17 +0200 Subject: [PATCH] Support both old and new architecture --- NativeLocationServicesDialogBox.ts | 10 ++++ android/build.gradle | 45 +++++++++++++-- ...ava => LocationServicesDialogBoxImpl.java} | 57 +++++++++++-------- .../LocationServicesDialogBoxPackage.java | 51 +++++++++++------ .../LocationServicesDialogBox.java | 42 ++++++++++++++ .../LocationServicesDialogBox.java | 37 ++++++++++++ index.js | 5 +- package.json | 10 +++- 8 files changed, 209 insertions(+), 48 deletions(-) create mode 100644 NativeLocationServicesDialogBox.ts rename android/src/main/java/com/showlocationservicesdialogbox/{LocationServicesDialogBoxModule.java => LocationServicesDialogBoxImpl.java} (88%) create mode 100644 android/src/newarch/com/showlocationservicesdialogbox/LocationServicesDialogBox.java create mode 100644 android/src/oldarch/com/showlocationservicesdialogbox/LocationServicesDialogBox.java diff --git a/NativeLocationServicesDialogBox.ts b/NativeLocationServicesDialogBox.ts new file mode 100644 index 0000000..11a5da6 --- /dev/null +++ b/NativeLocationServicesDialogBox.ts @@ -0,0 +1,10 @@ +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + checkLocationServicesIsEnabled: (config:Object) => Promise<{ status:string, enabled:boolean, alreadyEnabled:boolean }>; + forceCloseDialog: () => void; + stopListener: () => void; +} + +export default TurboModuleRegistry.getEnforcing('LocationServicesDialogBox'); \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 260d761..985dba1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,7 +1,23 @@ -apply plugin: 'com.android.library' +buildscript { + ext.safeExtGet = {prop, fallback -> + rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback + } + repositories { + google() + gradlePluginPortal() + } + dependencies { + classpath("com.android.tools.build:gradle:7.3.1") + } +} -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 { @@ -11,12 +27,33 @@ android { defaultConfig { minSdkVersion safeExtGet('minSdkVersion', 16) targetSdkVersion safeExtGet('targetSdkVersion', 26) + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() } lintOptions { warning 'InvalidPackage' } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += ['src/newarch'] + } else { + java.srcDirs += ['src/oldarch'] + } + } + } +} + +repositories { + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$projectDir/../node_modules/react-native/android" + } + mavenCentral() + google() } dependencies { - compileOnly 'com.facebook.react:react-native:+' + implementation 'com.facebook.react:react-native:+' + implementation 'com.google.android.play:review:2.0.1' } diff --git a/android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxModule.java b/android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxImpl.java similarity index 88% rename from android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxModule.java rename to android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxImpl.java index 2b8b2a7..f440e95 100644 --- a/android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxModule.java +++ b/android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxImpl.java @@ -2,18 +2,30 @@ import android.app.Activity; import android.app.AlertDialog; + import android.content.*; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; + import android.location.LocationManager; + import android.text.Html; import android.text.Spanned; + import android.view.Window; import android.widget.Button; + import com.facebook.react.bridge.*; import com.facebook.react.modules.core.DeviceEventManagerModule; -public class LocationServicesDialogBoxModule extends ReactContextBaseJavaModule implements ActivityEventListener { +import android.util.Log; + +public class LocationServicesDialogBoxImpl implements ActivityEventListener { + + public static final String NAME = "LocationServicesDialogBox"; + + static ReactApplicationContext RCTContext = null; + private Promise promiseCallback; private ReadableMap map; private Activity currentActivity; @@ -21,32 +33,25 @@ public class LocationServicesDialogBoxModule extends ReactContextBaseJavaModule private static AlertDialog alertDialog; private Boolean isReceive = false; private BroadcastReceiver providerReceiver = null; - private ReactApplicationContext RNContext; - LocationServicesDialogBoxModule(ReactApplicationContext reactContext) { - super(reactContext); - RNContext = reactContext; - reactContext.addActivityEventListener(this); + public LocationServicesDialogBoxImpl(ReactApplicationContext reactContext) { + RCTContext = reactContext; + RCTContext.addActivityEventListener(this); } - @Override - public void onNewIntent(Intent intent) { - } - - @Override - public String getName() { - return "LocationServicesDialogBox"; - } + /// + // API + // - @ReactMethod public void checkLocationServicesIsEnabled(ReadableMap configMap, Promise promise) { promiseCallback = promise; map = configMap; - currentActivity = getCurrentActivity(); - checkLocationService(false); + currentActivity = RCTContext.getCurrentActivity(); + if (currentActivity != null) { + checkLocationService(false); + } } - @ReactMethod public void forceCloseDialog() { try { if (alertDialog != null && alertDialog.isShowing() && promiseCallback != null) { @@ -55,18 +60,21 @@ public void forceCloseDialog() { } catch (Exception ignored) {} } - @ReactMethod public void stopListener() { isReceive = false; try { if (providerReceiver != null) { - getReactApplicationContext().unregisterReceiver(providerReceiver); + RCTContext.unregisterReceiver(providerReceiver); providerReceiver = null; } } catch (Exception ignored) { } } + /// + // Internals + // + private void checkLocationService(Boolean activityResult) { if (currentActivity == null || map == null || promiseCallback == null) return; LocationManager locationManager = (LocationManager) currentActivity.getSystemService(Context.LOCATION_SERVICE); @@ -177,7 +185,7 @@ private void newActivity(final Activity activity) { private void startListener() { try { providerReceiver = new LocationProviderChangedReceiver(); - getReactApplicationContext().registerReceiver(providerReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION)); + RCTContext.registerReceiver(providerReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION)); isReceive = true; } catch (Exception ignored) { } @@ -209,13 +217,16 @@ private void sendEvent() { params.putString("status", (enabled ? "enabled" : "disabled")); params.putBoolean("enabled", enabled); - if (RNContext != null) { - RNContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("locationProviderStatusChange", params); + if (RCTContext != null) { + RCTContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("locationProviderStatusChange", params); } } } } + @Override + public void onNewIntent(Intent intent) { } + @Override public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { if (requestCode == ENABLE_LOCATION_SERVICES) { diff --git a/android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxPackage.java b/android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxPackage.java index d0832d9..181c816 100644 --- a/android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxPackage.java +++ b/android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxPackage.java @@ -1,30 +1,45 @@ package com.showlocationservicesdialogbox; -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.JavaScriptModule; +import androidx.annotation.Nullable; + +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.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.HashMap; +import java.util.Map; -public class LocationServicesDialogBoxPackage implements ReactPackage { - @Override - public List createNativeModules(ReactApplicationContext reactApplicationContext) { - List modules = new ArrayList(); - modules.add(new LocationServicesDialogBoxModule(reactApplicationContext)); - return modules; - } +public class LocationServicesDialogBoxPackage extends TurboReactPackage { - // Deprecated RN 0.47 - public List> createJSModules() { - return Collections.emptyList(); + @Nullable + @Override + public NativeModule getModule(String name, ReactApplicationContext reactContext) { + if (name.equals(LocationServicesDialogBoxImpl.NAME)) { + return new LocationServicesDialogBox(reactContext); + } else { + return null; + } } @Override - public List createViewManagers(ReactApplicationContext reactApplicationContext) { - return Collections.emptyList(); + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return () -> { + final Map moduleInfos = new HashMap<>(); + boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + moduleInfos.put( + LocationServicesDialogBoxImpl.NAME, + new ReactModuleInfo( + LocationServicesDialogBoxImpl.NAME, + LocationServicesDialogBoxImpl.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + false, // hasConstants + false, // isCxxModule + isTurboModule // isTurboModule + )); + return moduleInfos; + }; } } diff --git a/android/src/newarch/com/showlocationservicesdialogbox/LocationServicesDialogBox.java b/android/src/newarch/com/showlocationservicesdialogbox/LocationServicesDialogBox.java new file mode 100644 index 0000000..a079d31 --- /dev/null +++ b/android/src/newarch/com/showlocationservicesdialogbox/LocationServicesDialogBox.java @@ -0,0 +1,42 @@ +package com.showlocationservicesdialogbox; + +import android.os.Build; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.Promise; + +import com.showlocationservicesdialogbox.NativeLocationServicesDialogBoxSpec; + +public class LocationServicesDialogBox extends NativeLocationServicesDialogBoxSpec { + + private final LocationServicesDialogBoxImpl delegate; + + public LocationServicesDialogBox(ReactApplicationContext reactContext) { + super(reactContext); + delegate = new LocationServicesDialogBoxImpl(reactContext); + } + + @NonNull + @Override + public String getName() { + return LocationServicesDialogBoxImpl.NAME; + } + + @Override + public void checkLocationServicesIsEnabled(ReadableMap configMap, Promise promise) { + delegate.checkLocationServicesIsEnabled(configMap,promise); + } + + @Override + public void forceCloseDialog() { + delegate.forceCloseDialog(); + } + + @Override + public void stopListener() { + delegate.stopListener(); + } +} \ No newline at end of file diff --git a/android/src/oldarch/com/showlocationservicesdialogbox/LocationServicesDialogBox.java b/android/src/oldarch/com/showlocationservicesdialogbox/LocationServicesDialogBox.java new file mode 100644 index 0000000..6e928b5 --- /dev/null +++ b/android/src/oldarch/com/showlocationservicesdialogbox/LocationServicesDialogBox.java @@ -0,0 +1,37 @@ +package com.showlocationservicesdialogbox; + +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.Promise; + +public class LocationServicesDialogBox extends ReactContextBaseJavaModule { + + private final LocationServicesDialogBoxImpl delegate; + + LocationServicesDialogBox(ReactApplicationContext reactContext) { + super(reactContext); + delegate = new LocationServicesDialogBoxImpl(reactContext); + } + + @Override + public String getName() { + return LocationServicesDialogBoxImpl.NAME; + } + + @ReactMethod + public void checkLocationServicesIsEnabled(ReadableMap configMap, Promise promise) { + delegate.checkLocationServicesIsEnabled(configMap,promise); + } + + @ReactMethod + public void forceCloseDialog() { + delegate.forceCloseDialog(); + } + + @ReactMethod + public void stopListener() { + delegate.stopListener(); + } +} diff --git a/index.js b/index.js index 78f3128..1ac7a01 100644 --- a/index.js +++ b/index.js @@ -1,2 +1,3 @@ -import { NativeModules } from 'react-native'; -export default NativeModules.LocationServicesDialogBox; \ No newline at end of file +import NativeLocationServicesDialogBox from './NativeLocationServicesDialogBox'; + +export default NativeLocationServicesDialogBox; \ No newline at end of file diff --git a/package.json b/package.json index dc5b7de..2bc97df 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,14 @@ "react-native-location-services-dialog-box" ], "peerDependencies": { - "react-native": ">= 0.56.0" + "react-native": ">= 0.68.0" + }, + "codegenConfig": { + "name": "LocationServicesDialogBoxSpec", + "type": "modules", + "jsSrcsDir": ".", + "android": { + "javaPackageName": "com.showlocationservicesdialogbox" + } } }