Expo应用生产环境授权位置权限后崩溃问题求助
Expo生产环境授权位置权限后应用崩溃(开发环境正常)
以下是针对该问题的常见排查方向和解决方案:
权限配置不完整
生产环境构建的应用需要在app.json/app.config.js中明确声明位置权限,Expo Go开发环境会自动处理权限,但正式包必须显式配置。检查expo.android.permissions数组,确保包含ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION:"android": { "permissions": [ "ACCESS_FINE_LOCATION", "ACCESS_COARSE_LOCATION" ] }位置请求的异步逻辑异常
生产环境中设备的位置服务可能存在延迟或不可用,getCurrentPositionAsync默认配置可能导致超时未处理引发崩溃。修改请求配置,增加超时限制并降低精度要求:const location = await Location.getCurrentPositionAsync({ timeout: 5000, enableHighAccuracy: false, maximumAge: 10000 });空值强制解包风险
代码中permissionDenied分支里使用currentLocation!强制解包,如果setDefaultLocationOnMap因异常未正确设置currentLocation,生产环境会触发空值崩溃。替换强制解包为安全判断:{currentLocation && ( <MapView style={styles.map} initialRegion={currentLocation} onPress={handlePress} > {marker && <Marker coordinate={marker}/>} </MapView> )}SDK版本兼容性问题
确认expo-location、react-native-maps与当前Expo SDK版本兼容,部分版本在生产构建中存在API行为差异。运行expo install expo-location react-native-maps确保依赖版本匹配,重新构建生产包。添加崩溃日志收集
集成Expo Crashlytics捕获生产环境崩溃日志,具体崩溃栈信息能快速定位问题:expo install expo-crashlytics
原组件代码
import React, {useState, useEffect} from 'react'; import {View, StyleSheet, Dimensions} from 'react-native'; import MapView, {Marker, Region} from 'react-native-maps'; import * as Location from 'expo-location'; import Loader from "../Loader"; interface LocationPickerProps { onLocationSelect?: (location: { latitude: number; longitude: number }) => void; selectedLocation?: { latitude: number; longitude: number } | null; } const LocationPicker = ({onLocationSelect, selectedLocation}: LocationPickerProps) => { const [currentLocation, setCurrentLocation] = useState<Region | null>(null); const [marker, setMarker] = useState<{ latitude: number; longitude: number } | null>(null); const [isLoading, setIsLoading] = useState(true); const [permissionDenied, setPermissionDenied] = useState(false); // Effect for requesting location permission and handling location update useEffect(() => { const requestLocationPermission = async () => { try { setIsLoading(true); const {status} = await Location.requestForegroundPermissionsAsync(); console.log("STATUS", status); if (status !== 'granted') { setPermissionDenied(true); setDefaultLocationOnMap(); return; } // If permissions are granted, fetch the location fetchLocation(); } catch (error) { // console.error('Error requesting location permission:', error); setDefaultLocationOnMap(); } finally { setIsLoading(false); } }; requestLocationPermission(); }, []); // Function to fetch and update location const fetchLocation = async () => { try { if (selectedLocation) { const region: Region = { latitude: selectedLocation.latitude, longitude: selectedLocation.longitude, latitudeDelta: 0.01, longitudeDelta: 0.01, }; setCurrentLocation(region); setMarker(selectedLocation); } else { const location = await Location.getCurrentPositionAsync({}); if (location && location.coords) { const {latitude, longitude} = location.coords; const region: Region = { latitude, longitude, latitudeDelta: 0.01, longitudeDelta: 0.01, }; setCurrentLocation(region); setMarker({latitude, longitude}); if (onLocationSelect) { onLocationSelect({latitude, longitude}) } } else { setDefaultLocationOnMap(); } } } catch (error) { // console.error('Error getting location:', error); setDefaultLocationOnMap(); } }; const setDefaultLocationOnMap = () => { const defaultLocation: Region = { latitude: 0, longitude: 0, latitudeDelta: 0.01, longitudeDelta: 0.01, }; setCurrentLocation(defaultLocation); }; const handlePress = (event: any) => { const coordinate = event.nativeEvent.coordinate; setMarker(coordinate); if (onLocationSelect) { onLocationSelect(coordinate); } }; if (isLoading) { return ( <View style={styles.loadingContainer}> <Loader/> </View> ); } if (permissionDenied) { return ( <View style={styles.container}> <MapView style={styles.map} initialRegion={currentLocation!} onPress={handlePress} > {marker && <Marker coordinate={marker}/>} </MapView> </View> ); } return ( <View style={styles.container}> {currentLocation && ( <MapView style={styles.map} initialRegion={currentLocation} onPress={handlePress} > {marker && <Marker coordinate={marker}/>} </MapView> )} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, map: { width: Dimensions.get('window').width, flex: 1, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); export default LocationPicker;
内容的提问来源于stack exchange,提问作者user2426691
相关产品推荐
相关产品推荐

