Deje que Android Module sepa que algunos permisos ya se conceden en la clase React-native

Estoy usando el paquete de pruebas reactrias para pedir permisos en mi aplicación. Cuando lo comienzo , la aplicación muestra el modal para aceptar los permisos solicitados después de eso llamo un método que requiere el permiso ACCESS_FINE_LOCATION aceptado. Así que cuando el código alcanza ese método obtengo el siguiente error:

2020-12-18 11:51:47.687 22777-22882/com.panicrn E/unknown:ReactNative: CatalystInstanceImpl caught native exception
    java.lang.SecurityException: ACCESS_FINE_LOCATION not granted. Please call `Activity.requestPermissions(String[], int)` first.
        at io.flic.flic2libandroid.Flic2Manager.checkScanPermission(Flic2Manager.java:486)
        at io.flic.flic2libandroid.Flic2Manager.startScan(Flic2Manager.java:506)
        at com.panicrn.FlicScanner.scanButtons(FlicScanner.java:35)
        at java.lang.reflect.Method.invoke(Native Method)

App.js:

  componentDidMount() {
    result = Permission.checkPermission(PERMISSION_TYPE.location)
    console.log("Result: "+result)
    if (result){
      FlicScanner.initFlicInstance();
      console.log("Scanning buttons")
      FlicScanner.scanButtons();
    }

AppPermissions.js:

const PLATFORM_FINE_LOCATION_PERMISSIONS = {
    android:  PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION
}

const REQUEST_PERMISSION_TYPE = {
    fineLocation: PLATFORM_FINE_LOCATION_PERMISSIONS
}

const PERMISSION_TYPE = {
    location: 'fineLocation'
}

class AppPermissions {

    checkPermission = async (type): Promise => {
        const permissions = REQUEST_PERMISSION_TYPE[type][Platform.OS]
        console.log(permissions)
        if (!permissions) {
            return true
        }
        try {
            const result = await check(permissions)
            if (result === RESULTS.GRANTED) return true
            return this.requestPermission(permissions)
        } catch (error) {
            return false
        }

    }

    requestPermission = async (permissions): Promise => {
        try{
            console.log("requestPermission result: "+(result === RESULTS.GRANTED))
            const result = await request(permissions)
            return result === RESULTS.GRANTED
        } catch (error) {
            return false
        }
    }

}

const Permission = new AppPermissions()
export { Permission, PERMISSION_TYPE }

FlicScanner.java:

package com.panicrn;

import android.Manifest;
import android.content.Intent;
import android.os.Handler;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;

import com.facebook.react.PackageList;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import io.flic.flic2libandroid.Flic2Button;
import io.flic.flic2libandroid.Flic2ButtonListener;
import io.flic.flic2libandroid.Flic2Manager;
import io.flic.flic2libandroid.Flic2ScanCallback;

public class FlicScanner extends ReactContextBaseJavaModule  {

    Flic2Manager manager;

    FlicScanner(ReactApplicationContext context){
        super(context);
    }

    @NonNull
    @Override
    public String getName() {
        return "FlicScanner";
    }

    @ReactMethod
    public void scanButtons() {
        Flic2Manager.getInstance().startScan(new Flic2ScanCallback() {
            @Override
            public void onDiscoveredAlreadyPairedButton(Flic2Button button) {

            }

            @Override
            public void onDiscovered(String bdAddr) {

            }

            @Override
            public void onConnected() {

            }

            @Override
            public void onComplete(int result, int subCode, Flic2Button button) {
                if (result == Flic2ScanCallback.RESULT_SUCCESS){
                    Toast.makeText(getReactApplicationContext(),"Connected button with MAC : "+button.getUuid(),Toast.LENGTH_SHORT).show();
                    addButtonListener(button);
                }
            }
        });
    }

    @ReactMethod
    public void initFlicInstance(){
        ContextCompat.startForegroundService(getReactApplicationContext(),new Intent(getReactApplicationContext(), FlicService.class));
        manager = Flic2Manager.initAndGetInstance(getReactApplicationContext(),new Handler());
    }

    @ReactMethod
    public void flicToast(){
        Toast.makeText(getReactApplicationContext(),"Pressed from Java module",Toast.LENGTH_SHORT).show();
    }

    public void addButtonListener(Flic2Button button) {
        button.addListener(new Flic2ButtonListener(){
            @Override
            public void onButtonSingleOrDoubleClickOrHold(Flic2Button button, boolean wasQueued, boolean lastQueued, long timestamp, boolean isSingleClick, boolean isDoubleClick, boolean isHold) {

                if (isSingleClick){
                    Toast.makeText(getReactApplicationContext(),"Has hecho un click al botón",Toast.LENGTH_SHORT).show();
                    return;
                }

                if (isDoubleClick){
                    Toast.makeText(getReactApplicationContext(),"Has hecho doble click al botón",Toast.LENGTH_SHORT).show();
                    return;
                }

                if (isHold){
                    Toast.makeText(getReactApplicationContext(),"Has mantenido el botón",Toast.LENGTH_SHORT).show();
                    return;
                }
            }
        });
    }
}

Estoy un poco confundido porque ya los estoy solicitando. Así que me gustaría saber si hay alguna manera de dejar que mi módulo nativo de androides sepa que los permisos ya se conceden. Gracias por adelantado :)

Pregunta hecha hace 3 años, 4 meses, 27 días - Por syntaxsenseie7e4


2 Respuestas:

  • Para informar al módulo nativo de Android que los permisos ya se han concedido, puedes modificar tu código de la siguiente manera:

    • En tu función `checkPermission` dentro de `AppPermissions.js`, cuando detectes que los permisos ya han sido concedidos, puedes enviar una señal al módulo nativo para que sepa que los permisos están disponibles. Por ejemplo, puedes agregar un código para enviar un evento de permisos concedidos al módulo nativo mediante el `ReactContext`, de la siguiente manera:
    js
    import { NativeModules } from 'react-native';
    
    class AppPermissions {
        // Otras funciones aquí...
    
        checkPermission = async (type): Promise => {
            const permissions = REQUEST_PERMISSION_TYPE[type][Platform.OS]
            console.log(permissions)
            if (!permissions) {
                return true
            }
            try {
                const result = await check(permissions)
                if (result === RESULTS.GRANTED) {
                    NativeModules.FlicScannerModule.permissionsGranted(); // Enviar evento de permisos concedidos al módulo nativo
                    return true
                }
                return this.requestPermission(permissions)
            } catch (error) {
                return false
            }
    
        }
    
        // Otras funciones aquí...
    }
    
    
    • En tu módulo nativo de `FlicScanner.java`, puedes agregar un método para recibir la señal de que los permisos están concedidos desde JavaScript:
    java
    import com.facebook.react.modules.core.DeviceEventManagerModule;
    
    // Dentro de la clase FlicScanner
    @ReactMethod
    public void permissionsGranted() {
        ReactApplicationContext context = getReactApplicationContext();
        context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("PERMISSIONS_GRANTED", null); // Aquí puedes enviar un evento opcional si lo deseas
    }
    

    Con estos cambios, cuando los permisos estén concedidos según lo detectado en JavaScript, se enviará una señal al módulo nativo de Android para indicar que los permisos ya han sido concedidos. Asegúrate de manejar este evento en el lado de JavaScript si es necesario para cualquier operación posterior que dependa de los permisos.

    Respondida el Dec 19, 2020 a las 11:22 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Solución:

    El problema es que el código de React Native solo verifica si los permisos ya están concedidos, pero no notifica al módulo nativo de Android sobre este estado. Para resolver este problema, debes enviar un evento desde React Native al módulo nativo de Android para indicar que los permisos ya están concedidos.

    Pasos:

    1. Crear un evento en React Native:

    En el archivo App.js, agrega el siguiente código para crear un evento que se enviará al módulo nativo de Android:

    javascript
    componentDidMount() {
      result = Permission.checkPermission(PERMISSION_TYPE.location)
      console.log("Result: "+result)
      if (result){
        FlicScanner.initFlicInstance();
        console.log("Scanning buttons")
        FlicScanner.scanButtons();
        NativeEventEmitter.emit("PermissionGranted", { type: PERMISSION_TYPE.location });
      }
    }
    

    2. Registrarse para el evento en el módulo nativo de Android:

    En el archivo FlicScanner.java, registra un NativeEventEmitter para escuchar el evento "PermissionGranted":

    java
    @Override
    public void initialize() {
        super.initialize();
    
        // Registrarse para el evento "PermissionGranted"
        ReactContext context = getReactApplicationContext();
        NativeEventEmitter eventEmitter = new NativeEventEmitter(context);
        eventEmitter.addListener("PermissionGranted", new ReactNativeEventEmitterListener() {
            @Override
            public void onReceiveEvent(String eventName, @Nullable ReadableMap params) {
                if ("PermissionGranted".equals(eventName)) {
                    // Los permisos ya están concedidos en React Native
                    // Puedes inicializar el escaneo aquí
                }
            }
        });
    }
    

    3. Inicializar el escaneo después de recibir el evento:

    En el método onReceiveEvent, inicializa el escaneo cuando recibas el evento "PermissionGranted".

    java
    if ("PermissionGranted".equals(eventName)) {
        manager.startScan(new Flic2ScanCallback() {
            // ... Código de escaneo
        });
    }
    

    4. Actualizaciones de dependencias:

    Asegúrate de que tienes las siguientes dependencias instaladas:

    react-native-permissions react-native-flic

    Nota:

    Utiliza el nombre de evento "PermissionGranted" o cámbialo según sea necesario en tu aplicación. Este enfoque solo funcionará si el módulo nativo de Android está registrado como un módulo de paquete en el archivo MainActivity.java.

    Respondida el Dec 19, 2020 a las 11:25 - por Gemini

    Votos positivos: 0 | Votos negativos: 0