首页 > 解决方案 > React-native android bridge 请求许可

问题描述

我有一个负责请求某些权限的本机 Java 模块,并且我创建了一个桥来访问 JavaScript 中的此方法。这是 react-native 代码的相关部分

import { NativeModules, Platform } from 'react-native';
  
const CTModule = NativeModules.CTHandler as {
  requestPermissions: () => Promise<boolean>;
  arePermissionsGranted: () => Promise<boolean>;
  enableAndDiscoverableBluetooth: () => Promise<boolean>;
  startBluetoothService: () => Promise<boolean>;
};

export const enableCT = async () => {
  const areGranted = await CTModule.arePermissionsGranted();
  if (!areGranted) {
    await CTModule.requestPermissions();
  }
  await CTModule.enableAndDiscoverableBluetooth();
  await CTModule.startBluetoothService();
};

为简单起见,假设enableCT当用户按下按钮时调用该函数。

问题是等待不起作用,例如await CTModule.requestPermissions();不等待任何时间,因此根本不会出现请求权限的对话框。此代码await CTModule.enableAndDiscoverableBluetooth();也不会等待任何时间,它也会立即执行。

这是Java代码CTModule

public class CTHandlerModule extends ReactContextBaseJavaModule implements PermissionListener, ActivityEventListener {
    private static ReactApplicationContext reactContext;
    private static final int permissionsRequestCode = 1;
    private static Promise requestingPermissions = null;
    private static Promise bltPromise = null;
    private static Promise bltServiceStart = null;
    private static final int BLUETOOTH_ENABLE_CODE = 123;


    CTHandlerModule(ReactApplicationContext context) {
        super(context);
        reactContext = context;
    }
    
    @ReactMethod
    public void requestPermissions(final Promise promise) {
        if(requestingPermissions != null) {
            promise.reject("IN_PROGRESS", "Requesting permissions in progress");
            return;
        }
        requestingPermissions = promise;
        requestAndroidPermissions();
    }

    @ReactMethod
    public void arePermissionsGranted(final Promise promise) {
        boolean areGranted = areAndroidPermissionsGranted();
        promise.resolve(areGranted);
    }

    @ReactMethod
    public void enableAndDiscoverableBluetooth(final Promise promise) {
        if(bltPromise != null) {
            promise.reject("IN_PROGRESS", "Enabling bluetooth in progress");
            return;
        }
        bltPromise = promise;
        androidEnableBluetooth();
    }

    @ReactMethod
    public void startBluetoothService(final Promise promise) {
        if(bltServiceStart != null) {
            promise.reject("IN_PROGRESS", "Bluetooth service start in progress");
            return;
        }
        bltServiceStart = promise;
        startAndroidBluetoothService();
    }

    @ReactMethod
    public void stopBluetoothService(final Promise promise) {
        if (BTScanningService.serviceRunning) {
            MainUtils.stopBackgroundWorker();
        }
        promise.resolve(true);
    }

    @ReactMethod
    public void isCTModuleRunning(final Promise promise) {
        promise.resolve(BTScanningService.serviceRunning);
    }

    private void startAndroidBluetoothService() {
        if(areAndroidPermissionsGranted()) {
            String uniqueId = SharedPref.getStringParams(
                    MainApplication.getInstance(), SharedPrefConstants.UNIQUE_ID, ""
            );
            if (!uniqueId.isEmpty()) {
                Intent intent = new Intent(reactContext.getCurrentActivity(), BTScanningService.class);
                ContextCompat.startForegroundService(reactContext.getCurrentActivity(), intent);
            }
            MainUtils.startBackgroundWorker();
            bltServiceStart.resolve(true);
            bltServiceStart = null;
        } else {
            bltServiceStart.reject("PERMISSIONS_NOT_GRANTED", "Bluetooth permissions are not granted");
            bltServiceStart = null;
        }
    }

    private boolean androidEnableBluetooth() {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null) {
            bltPromise.reject("NO_BLUETOOTH", "No Bluetooth on this handset");
            bltPromise = null;
            return true;
        }
        if(!adapter.isEnabled()) {
            enableBluetooth();
            return false;
        }
        if(adapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            makeBluetoothDiscoverable();
            return false;
        }
        bltPromise.resolve(true);
        bltPromise = null;
        return true;
    }

    public void makeBluetoothDiscoverable() {
        Intent bltDiscoverable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        bltDiscoverable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300000);
        reactContext.getCurrentActivity().startActivityForResult(bltDiscoverable, BLUETOOTH_ENABLE_CODE);
    }

    private void enableBluetooth() {
        Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        reactContext.getCurrentActivity().startActivityForResult(enableBT, BLUETOOTH_ENABLE_CODE);
    }

    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
        if (requestCode == BLUETOOTH_ENABLE_CODE) {
            androidEnableBluetooth();
        }
    }

    public void requestAndroidPermissions() {
        MainUtils.requestPermissions(
                reactContext.getCurrentActivity(),
                permissionsRequestCode
        );
    }

    @Override
    public boolean onRequestPermissionsResult(
            int requestCode, String[] permissions, int[] grantResults) {

        if(requestCode == permissionsRequestCode) {
            boolean areGranted = areAndroidPermissionsGranted();
            requestingPermissions.resolve(areGranted);
            requestingPermissions = null;
            return true;
        }
        requestingPermissions.reject("NOT_GRANTED", "Permissions where not granted");
        requestingPermissions = null;
        return false;
    }


    public boolean areAndroidPermissionsGranted() {
        return MainUtils.arePermissionsGranted(reactContext.getCurrentActivity());
    }

}

这段代码调用了 helper 模块的一些函数 - MainUtils,代码如下:

public class MainUtils {

    public static boolean isBluetoothAvailable() {
        if(isBluetoothPermissionAvailable(MainApplication.getInstance().getApplicationContext())) {
            BluetoothAdapter bltAdapter = BluetoothAdapter.getDefaultAdapter();
            return bltAdapter != null &&
                   bltAdapter.isEnabled() &&
                   bltAdapter.getState() == BluetoothAdapter.STATE_ON;
        }
        return false;
    }

    public static boolean isBluetoothPermissionAvailable(Context context) {
        int blt = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH);
        int bltadmin = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN);
        return (blt == PackageManager.PERMISSION_GRANTED && bltadmin == PackageManager.PERMISSION_GRANTED);
    }

    public static boolean isBTScanningServiceRunning() {
        return BTScanningService.serviceRunning;
    }

    public static void requestPermissions(
        Activity context, int permissionRequestCode
    ) {
        String[] PERMISSIONS = {
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN,
                Manifest.permission.ACCESS_COARSE_LOCATION,
        };
        ActivityCompat.requestPermissions(
                context,
                PERMISSIONS,
                permissionRequestCode
        );
    }

    public static boolean arePermissionsGranted(Context context) {
        int blt = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH);
        int bltadmin = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN);
        int coarseLoc = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION);

        return (
                blt == PackageManager.PERMISSION_GRANTED
                && bltadmin == PackageManager.PERMISSION_GRANTED
                && coarseLoc == PackageManager.PERMISSION_GRANTED
        );
    }

}

标签: javaandroidreact-nativepromisereact-native-android

解决方案


推荐阅读