Ausgabe
Ich verwende die Flatterkarte und möchte den Gerätestandort mithilfe des Geolocator-Pakets abrufen, aber es funktioniert nicht.
Dies funktioniert perfekt unter Windows (Desktop) und Chrome/Edge Web . Es funktioniert jedoch nicht auf dem Android-Emulator .
Ich habe bereits die Anweisungen in diesem Thread befolgt, aber ohne Erfolg. Insbesondere habe ich eine Position mit den Emulatoreinstellungen konfiguriert und auf die Schaltfläche “Standort festlegen” geklickt.
Ich habe auch eine Route in den Einstellungen des Android-Emulators eingerichtet und die Wiederholung der Wiedergabe ausgewählt.
Für mein Android-Manifest habe ich versucht, nur das ACCESS_COARSE_LOCATION
und nur das zu verwenden ACCESS_FINE_LOCATION
, aber immer noch ohne Erfolg. Ich habe auch versucht, die beiden gleichzeitig zu verwenden, aber es hat immer noch nicht funktioniert.
Geolocator-Version:
PS : Ich habe die Anweisungen auf der offiziellen Seite des Pakets befolgt .
PSS : Als ich die App auf dem Emulator ausführte, wurde nicht einmal das Popup-Fenster angezeigt, in dem um Erlaubnis zum Zugriff auf den Standort gebeten wurde.
Nachfolgend meine Codes:
compileSdkVersion 33
Gradle.properties
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
Android-Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.spot_the_bird">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:label="spot_the_bird"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Ort Elle:
import 'dart:developer';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:geolocator/geolocator.dart';
part 'location_state.dart';
class LocationCubit extends Cubit<LocationState> {
LocationCubit() : super(const LocationInitial());
Future<void> getLocation() async {
LocationPermission locationPermission = await Geolocator.checkPermission();
if (locationPermission != LocationPermission.denied ||
locationPermission != LocationPermission.deniedForever) {
emit(const LocationLoading());
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
log("$position");
emit(LocationLoaded(
longitude: position.longitude, latitude: position.latitude));
} catch (error) {
emit(const LocationError(
message: 'Error occured while fetching location'));
}
} else {
Geolocator.requestPermission();
}
}
}
Standort Staat:
part of 'location_cubit.dart';
abstract class LocationState extends Equatable {
const LocationState();
@override
List<Object?> get props => [];
}
class LocationInitial extends LocationState {
const LocationInitial();
}
class LocationLoading extends LocationState {
const LocationLoading();
}
class LocationLoaded extends LocationState {
const LocationLoaded({
required this.longitude,
required this.latitude,
});
final double longitude;
final double latitude;
@override
List<Object?> get props => [latitude, longitude];
}
class LocationError extends LocationState {
final String message;
const LocationError({
required this.message,
});
}
Kartenbildschirm
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:spot_the_bird/bloc/location_cubit.dart';
class MapScreen extends StatelessWidget {
MapScreen({super.key});
final MapController _mapController = MapController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: BlocListener<LocationCubit, LocationState>(
listener: (prevState, currState) {
if (currState is LocationError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(currState.message),
duration: const Duration(seconds: 3),
backgroundColor: Theme.of(context).errorColor,
),
);
}
if (currState is LocationLoaded) {
_mapController.onReady.then((value) => _mapController.move(
LatLng(currState.latitude, currState.longitude), 15));
}
},
child: FlutterMap(
mapController: _mapController,
options: MapOptions(
center: LatLng(4.8472226, 6.974604),
zoom: 15,
minZoom: 4,
),
layers: [
TileLayerOptions(
urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
subdomains: ['a', 'b', 'c'],
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<LocationCubit>().getLocation();
},
child: const Icon(Icons.navigation_outlined),
),
);
}
}
Abhängigkeiten in pubspec.yaml
flutter:
sdk: flutter
flutter_map: ^2.2.0
latlong2: ^0.8.1
geolocator: ^9.0.2
flutter_bloc: ^8.1.1
equatable: ^2.0.5
bloc: ^8.1.0
cupertino_icons: ^1.0.2
Lösung
Das Problem war mit meiner location.cubit. Seltsamerweise, als ich nach dem location.denied
und location.deniedPermanantly
separat gesucht habe, hat es funktioniert.
Unten ist mein neuer location.cubit-Code:
Future<void> getLocation() async {
// bool serviceEnabled;
LocationPermission permission;
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
Get.snackbar('', 'Location Permission Denied');
return Future.error('Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately.
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
} else {
emit(const LocationLoading());
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
log("$position");
emit(LocationLoaded(
longitude: position.longitude, latitude: position.latitude));
} catch (error) {
emit(const LocationError(
message: 'Error occured while fetching location'));
}
}
}
PS: Übrigens, Dank an @ibrahim Eltayfe , durch das Hinzufügen von <uses-permission android:name="android.permission.INTERNET"/>
wurde mir das Problem in der Debug-Konsole angezeigt. Danke, Mann.
Beantwortet von – Diraph
Antwort geprüft von – Pedro (FixError Volunteer)