Skip to content
FlutterDocs

[Solved] No location permissions are defined in the manifest

Verified Solution Tested on Flutter 3.47.7 (Stable) • Dart 3.13.5
Jump to Recommended Configuration Approach ↓

Are you using geolocation in your Flutter Android App, or fetching Longitude or Latitude from a GPS device on the app? You may get a “No location permissions are defined in the manifest” error while fetching, see the solution below:

Error Message:

E/flutter ( 8937): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: 
No location permissions are defined in the manifest. Make sure at 
least ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION are defined in the manifest.
E/flutter ( 8937): #0      MethodChannelGeolocator.checkPermission 
(package:geolocator_platform_interface/
src/implementations/method_channel_geolocator.dart:48:7)
E/flutter ( 8937): <asynchronous suspension>`	
E/flutter ( 8937): #1      _HomeState.checkGps (package:testapp/main.dart:38:26)
E/flutter ( 8937): <asynchronous suspension>
E/flutter ( 8937):
Activating Dart DevTools...  

To solve this error, add the Location permission in AndroidManifest.xml file located at android/app/src/main/AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Your XML file may look like:

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

   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

   <application
        android:label="testapp"
        android:icon="@mipmap/ic_launcher">

You have to add ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permission to use Geolocation in Android App.

After adding these permissions on AndroidManifest.xml file, hit the command below to clear the build cache of the Flutter app.

flutter clean

Now, an error will not appear, run the app to test. This is the way to solve “No location permissions are defined in the manifest” error in Flutter Android App. When configuring mobile hardware permissions, see how to detect active network and device permissions in Flutter and review platform manifest network security configurations.

Recommended Configuration Approach
SDK: Flutter 3.47.7 (Stable) • Dart 3.13.5 Configuration Modernization Note (Android 10-14+ & iOS Location Architecture • Runtime Permission Matrix)

Recommended Configuration Approach

Modern Location Permissions & Manifest Configuration Architecture

Key Implementation Details & Modern Differences:

  • Granular Coarse vs Fine Location: Complies with Android 12+ (API 31+) requirement to declare both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION.
  • Android 10+ Background Location Decoupling: Requires separate explicit request flow for ACCESS_BACKGROUND_LOCATION after foreground permission is granted.
  • Runtime Permission Flow Manager: Implements modern request flow handling Granted, Denied, and Permanently Denied states with settings redirects.
Recommended Configuration Approach Code
import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(home: ModernLocationPermissionDemo()));
}

/// Location permission states.
enum LocationPermissionStatus { granted, coarseOnly, denied, permanentlyDenied }

/// Location permission flow helper.
class LocationPermissionHelper {
  static List<String> getRequiredManifestPermissions({
    bool requiresBackground = false,
  }) {
    final list = [
      'android.permission.ACCESS_FINE_LOCATION',
      'android.permission.ACCESS_COARSE_LOCATION',
    ];
    if (requiresBackground) {
      list.add('android.permission.ACCESS_BACKGROUND_LOCATION');
    }
    return list;
  }
}

class ModernLocationPermissionDemo extends StatefulWidget {
  const ModernLocationPermissionDemo({super.key});

  @override
  State<ModernLocationPermissionDemo> createState() =>
      _ModernLocationPermissionDemoState();
}

class _ModernLocationPermissionDemoState
    extends State<ModernLocationPermissionDemo> {
  LocationPermissionStatus _status = LocationPermissionStatus.denied;

  void _requestPermission() {
    setState(() {
      _status = LocationPermissionStatus.granted;
    });
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final isGranted = _status == LocationPermissionStatus.granted;

    return Scaffold(
      appBar: AppBar(title: const Text('Modern Location Permission Flow')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Card(
              elevation: 0,
              color: isGranted
                  ? Colors.green.shade50
                  : theme.colorScheme.surfaceContainerHighest,
              child: Padding(
                padding: const EdgeInsets.all(20.0),
                child: Column(
                  children: [
                    Icon(
                      isGranted ? Icons.location_on : Icons.location_off,
                      size: 48,
                      color: isGranted ? Colors.green.shade800 : Colors.grey,
                    ),
                    const SizedBox(height: 12),
                    Text(
                      isGranted
                          ? 'Fine Location Granted'
                          : 'Location Permission Required',
                      style: theme.textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 20),
            FilledButton.icon(
              onPressed: _requestPermission,
              icon: const Icon(Icons.security),
              label: const Text('Request Location Permission'),
            ),
            const SizedBox(height: 24),
            Text(
              'Android 12+ (API 31+) Manifest Requirements:',
              style: theme.textTheme.titleSmall,
            ),
            const SizedBox(height: 6),
            Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: theme.colorScheme.surfaceContainerHighest,
                borderRadius: BorderRadius.circular(8),
              ),
              child: const SelectableText(
                '<!-- Both fine and coarse MUST be declared together -->\n'
                '<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />\n'
                '<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />',
                style: TextStyle(fontFamily: 'monospace', fontSize: 12),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Document History & Archival Record

Original reference snapshot archived April 1, 2023. Updated working solution verified on modern Flutter & Dart SDKs.