React Native Android应用提取图片GPS EXIF数据异常,坐标被重置为0的排查求助
React Native Android应用提取图片GPS EXIF数据异常,坐标被重置为0的排查求助
我正在开发一个React Native Android应用,核心功能是上传图片后,根据图片EXIF信息里的GPS坐标把它标记在地图上,但现在遇到了棘手的问题——提取到的GPS坐标总是被重置为0,完全找不到原因,想请教下大家的排查思路!下面是我的App.js代码,要是需要看其他部分也随时说~
import React, { useEffect, useState } from 'react'; import { View, StyleSheet, Image, Text, TouchableOpacity, Modal, useWindowDimensions, Alert, Platform } from 'react-native'; import MapView, { Marker } from 'react-native-maps'; import * as MediaLibrary from 'expo-media-library'; import * as ImagePicker from 'expo-image-picker'; import * as Location from 'expo-location'; import * as FileSystem from 'expo-file-system'; // Example baked-in image URIs (images stored in your app's assets folder) const bakedInImages = [ { id: 'baked-1', uri: require('./assets/images/king_tee.jpg'), // Local image latitude: 37.7749, longitude: -122.4194, }, { id: 'baked-2', uri: require('./assets/images/winter_photo.png'), // Local image latitude: 34.0522, longitude: -118.2437, }, ]; export default function App() { const [markers, setMarkers] = useState([]); const [modalVisible, setModalVisible] = useState(false); const [selectedImage, setSelectedImage] = useState(null); const { width, height } = useWindowDimensions(); // Get screen dimensions for full-screen modal const [currentLocation, setCurrentLocation] = useState({ latitude: 37.0902, longitude: -95.7129, }); const [mapRegion, setMapRegion] = useState({ latitude: 37.0902, longitude: -95.7129, latitudeDelta: 30, longitudeDelta: 30, }); const [manualLocationMode, setManualLocationMode] = useState(false); const [pendingImage, setPendingImage] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const requestPermissionsAndFetchAssets = async () => { setIsLoading(true); try { // Request all necessary permissions at startup console.log("Requesting media library permissions..."); const mediaPermission = await MediaLibrary.requestPermissionsAsync(); console.log("Requesting location permissions..."); const locationPermission = await Location.requestForegroundPermissionsAsync(); // Special request for Android's media location permission if (Platform.OS === 'android') { console.log("Requesting media location permissions (Android)..."); const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(true); console.log("Media location permission status:", status); } if (mediaPermission.status !== 'granted') { Alert.alert('Permission required', 'Permission to access photos is required!'); setIsLoading(false); return; } // Get user's current location if (locationPermission.status === 'granted') { try { console.log("Getting current location..."); const location = await Location.getCurrentPositionAsync({}); const userLocation = { latitude: location.coords.latitude, longitude: location.coords.longitude, }; setCurrentLocation(userLocation); setMapRegion({ ...userLocation, latitudeDelta: 0.1, longitudeDelta: 0.1, }); console.log("Current location set:", userLocation); } catch (error) { console.log('Error getting location:', error); } } // Load photos with location from the media library try { console.log("Fetching assets from media library..."); const assets = await MediaLibrary.getAssetsAsync({ mediaType: 'photo', first: 20, }); console.log(`Found ${assets.assets.length} assets`); const photosWithGPS = []; for (let asset of assets.assets) { try { // Get full asset info to ensure we have location data const assetInfo = await MediaLibrary.getAssetInfoAsync(asset); // Check if the asset has location data if (assetInfo.location) { console.log(`Asset ${assetInfo.id} has location data:`, assetInfo.location); photosWithGPS.push({ id: assetInfo.id, uri: assetInfo.uri, latitude: assetInfo.location.latitude, longitude: assetInfo.location.longitude, }); } } catch (error) { // Skip this asset if there's an error console.log('Error processing asset:', error); } } console.log(`Found ${photosWithGPS.length} photos with GPS data`); setMarkers([...photosWithGPS, ...bakedInImages]); // Combine device photos and baked-in images } catch (error) { console.error('Error loading media library:', error); } } catch (error) { console.error("Error during initialization:", error); } finally { setIsLoading(false); } }; requestPermissionsAndFetchAssets(); }, []); // Function to attempt to extract EXIF/location data from an image const tryGetImageLocation = async (imageUri) => { console.log("Attempting to extract location from image:", imageUri); try { // Try to get the file info first const fileInfo = await FileSystem.getInfoAsync(imageUri); console.log("File info:", fileInfo); if (!fileInfo.exists) { console.log("File does not exist"); return null; } // 目前这里的逻辑依赖MediaLibrary,但提取结果异常 } catch (error) { console.log('Error extracting location:', error); return null; } }; // 图片选择、模态框等其他组件渲染逻辑省略 }
我目前的排查方向和疑问:
- 权限问题:已经请求了媒体库权限、前台位置权限,还有Android专属的
ACCESS_MEDIA_LOCATION权限(通过ImagePicker.requestMediaLibraryPermissionsAsync(true)),日志显示权限都是granted,但会不会有隐藏的权限配置遗漏? - 数据提取方式:我用
MediaLibrary.getAssetInfoAsync(asset)获取location,但部分明明带GPS信息的图片(手机相册能看到位置),返回的location却是{latitude:0, longitude:0},这个API是不是有什么限制? - 系统版本限制:测试设备是Android 11,会不会是系统隐私限制导致无法读取EXIF里的GPS数据?
求各位大佬给点建议,比如有没有更可靠的提取EXIF GPS的方式,或者权限配置上的坑,或是代码里没注意到的细节?
内容来源于stack exchange
相关产品推荐
相关产品推荐

