6

I am trying to use a simple Flutter plugin (speech recognition wrapper) and have no idea how to request the appropriate permissions on Android 23 or newer. In the Dart part I have:

  Future requestPermissions() => 
  _channel.invokeMethod("speech.requestPermissions");

In the Android part:

  public class SpeechRecognitionPlugin implements MethodCallHandler, RecognitionListener,
    PluginRegistry.RequestPermissionResultListener {

Plugin registration:

  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "speech_recognition");
    SpeechRecognitionPlugin speechRecognitionPlugin = new 
    SpeechRecognitionPlugin(registrar.activity(), channel);
    channel.setMethodCallHandler(speechRecognitionPlugin);
    registrar.addRequestPermissionResultListener(speechRecognitionPlugin);
  }

Method call:

else if (call.method.equals("speech.requestPermissions")) {
        Log.d(LOG_TAG, "speech.requestPermissions");
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
                Manifest.permission.RECORD_AUDIO)) {
            Toast.makeText(activity.getApplicationContext(), "This application needs the Record Audio permission for recognition to work", Toast.LENGTH_LONG).show();
        } else {
            Log.d(LOG_TAG, "Requesting permissions");
            ActivityCompat.requestPermissions(activity,
                    new String[]{Manifest.permission.RECORD_AUDIO},
                    1);
        }
        result.success(hasRecordAudioPermission());

Result callback:

@Override                                                                                            
public boolean onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
    boolean granted = false;
    switch (requestCode) {
        case 1: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                granted = true;
            }
            speechChannel.invokeMethod("speech.onPermission", granted);
            return true;
        }
    }
    return false;
}

From logcat I see that the "speech.requestPermissions" call happens, but standard Android system permission request is not shown, just this in the logcat may be related:

D/ViewRootImpl(21171): #1 mView = android.widget.LinearLayout{64f050b 
V.E...... ......I. 0,0-0,0 #102039d android:id/toast_layout_root}
D/ViewRootImpl(21171): MSG_RESIZED_REPORT: ci=Rect(0, 0 - 0, 0) vi=Rect(0, 0 - 0, 0) or=1
D/ViewRootImpl(21171): #3 mView = null

What is the correct way to request permissions for Flutter plugins?

EDIT: This does not apply to the first run, when the dialog shows correctly, but to subsequent runs when the user did not grant the permission at first or revoked it via settings. I realize that changes the question significantly (making it appear as edge case), but Android permissions are not supposed to work that way.

EDIT: The permissions are present in AndroidManifest.xml

3 Answers 3

5

Use Permission plugin for flutter

Request permission
import 'package:permissions_plugin/permissions_plugin.dart';

Map<Permission, PermissionState> permission = await PermissionsPlugin
    .requestPermissions([
        Permission.ACCESS_FINE_LOCATION,
        Permission.ACCESS_COARSE_LOCATION,
        Permission.READ_PHONE_STATE
    ]);
Check status permission
import 'package:permissions_plugin/permissions_plugin.dart';

Map<Permission, PermissionState> permission = await PermissionsPlugin
    .checkPermissions([
      Permission.ACCESS_FINE_LOCATION,
      Permission.ACCESS_COARSE_LOCATION,
      Permission.READ_PHONE_STATE
    ]);
Sign up to request clarification or add additional context in comments.

1 Comment

In this package is mentioned, that it only for now supports just android.
0

I have this working for location permissions. The only thing I'm doing differently is in your method call here:

ActivityCompat.requestPermissions(activity,
                new String[]{Manifest.permission.RECORD_AUDIO},
                1);

Instead of using 'ActivityCompat' I store the registrar in a local final variable and I'm doing the following :

registrar.activity().requestPermissions(activity,
                new String[]{Manifest.permission.RECORD_AUDIO},
                1);

EDIT: Also make sure that you have included the relevant permissions in your AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Add this -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <!-- Flutter stuff --->
</manifest>

9 Comments

Thanks for assuring that this is at least a way to go. I have edited the question, first run works, but requesting permissions on the fly does not. Sorry for not mentioning it before.
You will have to add the permission to the manifest as well (if you haven't already done that). See my edited answer for an example
How are you checking to see if the permission has or hasn't already been granted? I'm using this in my plugin: PermissionChecker.checkSelfPermission(registrar.activity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
int permissionCheck = ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO); return (permissionCheck == PackageManager.PERMISSION_GRANTED); I will try your version when I get to the code.
Unfortunately, no change. Now that I think about it, I do not know what did I expect from this change, the permission request call is no different.
|
-1

Let's say you want to request camera permission using permission_handler package.

  1. In pubspec.yaml file:

    permission_handler: ^8.0.0+2
    
  2. (For Android) Add the permission to android/app/src/main/AndroidManifest.xml file

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 
      ...
     </manifest>
    
  3. (For iOS),

    (i) Add this to your info.plist file

    <key>NSCameraUsageDescription</key>
    <string>App needs camera permission to work</string>
    

    (ii) Add 'PERMISSION_CAMERA=1' to your Podfile.

    post_install do |installer|
      installer.pods_project.targets.each do |target|
        flutter_additional_ios_build_settings(target)
    
        target.build_configurations.each do |config|
          config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
            '$(inherited)',
    
            ## Add the following line.
             'PERMISSION_CAMERA=1'
          ]
    
        end
      end
    end
    
  4. Request the permission:

    final status = await Permission.camera.request();
    if (status == PermissionStatus.granted) {
      print('Permission granted');
    } else if (status == PermissionStatus.denied) {
      print('Permission denied. Show a dialog and again ask for the permission');
    } else if (status == PermissionStatus.permanentlyDenied) {
      print('Take the user to the settings page.');
      await openAppSettings();
    }
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.