Skip to content

Support both old and new architecture #83

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
10 changes: 10 additions & 0 deletions NativeLocationServicesDialogBox.ts
Original file line number Diff line number Diff line change
@@ -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<Spec>('LocationServicesDialogBox');
45 changes: 41 additions & 4 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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'
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,56 @@

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;
private static final int ENABLE_LOCATION_SERVICES = 1009;
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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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) {
}
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext) {
List<NativeModule> modules = new ArrayList<NativeModule>();
modules.add(new LocationServicesDialogBoxModule(reactApplicationContext));
return modules;
}
public class LocationServicesDialogBoxPackage extends TurboReactPackage {

// Deprecated RN 0.47
public List<Class<? extends JavaScriptModule>> 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<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
return Collections.emptyList();
public ReactModuleInfoProvider getReactModuleInfoProvider() {
return () -> {
final Map<String, ReactModuleInfo> 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;
};
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import { NativeModules } from 'react-native';
export default NativeModules.LocationServicesDialogBox;
import NativeLocationServicesDialogBox from './NativeLocationServicesDialogBox';

export default NativeLocationServicesDialogBox;
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}