You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 12:14:30