Reagieren Sie native Foto -GPS -ExtraktionAndroid

Forum für diejenigen, die für Android programmieren
Anonymous
 Reagieren Sie native Foto -GPS -Extraktion

Post by Anonymous »

Ich entwerfe eine reag -native App für Android. Der Zweck der Anwendung ist es, ein Bild hochzuladen und auf der Karte basierend auf den in den EXIF ​​-Informationen gespeicherten GPS -Koordinaten zu platzieren. Derzeit scheint die Anwendung die GPS -Koordinaten auf 0 zurückzusetzen. Ich bin mir nicht sicher, warum und möchte einige Eingaben. < /P>
Hier ist mein App.js -Code. Wenn Sie etwas anderes sehen möchten, lassen Sie es mich wissen! < /P>

Code: Select all

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;
}

// For Android with the proper permissions, we can try to get the asset
if (Platform.OS === 'android') {
try {
// Try to find the asset in the media library
const uriParts = imageUri.split('/');
const filename = uriParts[uriParts.length - 1];

// Search for the asset
const query = filename.split('.')[0];  // Remove extension for better search
const mediaAssets = await MediaLibrary.getAssetsAsync({
first: 10,
sortBy: [['creationTime', false]],
});

// Find the matching asset
for (const asset of mediaAssets.assets) {
try {
const assetInfo = await MediaLibrary.getAssetInfoAsync(asset);
if (assetInfo.uri.includes(query) || imageUri === assetInfo.uri) {
console.log("Found matching asset with location:", assetInfo.location);
if (assetInfo.location) {
return {
latitude: assetInfo.location.latitude,
longitude: assetInfo.location.longitude
};
}
}
} catch (error) {
console.log("Error checking asset:", error);
}
}
} catch (error) {
console.log("Error searching media library:", error);
}
}

// If we get here, we couldn't find location data
console.log("No location data found for this image");
return null;
} catch (error) {
console.error("Error extracting location data:", error);
return null;
}
};

// Handle opening the modal for full-screen image
const openModal = (image) => {
setSelectedImage(image.uri);
setModalVisible(true);
};

// Handle closing the modal
const closeModal = () => {
setModalVisible(false);
setSelectedImage(null);
};

// Handle map press for manual location selection
const handleMapPress = (event) => {
if (manualLocationMode && pendingImage) {
// Get coordinates from the press event
const { coordinate } = event.nativeEvent;

// Create a new marker with the selected image and the tapped location
const newMarker = {
id: pendingImage.uri,
uri: pendingImage.uri,
latitude: coordinate.latitude,
longitude: coordinate.longitude,
};

// Add the new marker
setMarkers(prevMarkers => [...prevMarkers, newMarker]);

// Reset manual mode and pending image
setManualLocationMode(false);
setPendingImage(null);

// Show confirmation
Alert.alert("Image Added", "The image has been added to the map at the selected location.");
}
};

const handleImagePicker = async () => {
// Request permission for media library
console.log("Requesting media library permissions...");
const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync(
Platform.OS === 'android' ? true : false
);

if (permissionResult.granted === false) {
Alert.alert('Permission required', 'Permission to access media library is required!');
return;
}

// Launch image picker
console.log("Launching image picker...");
const pickerResult = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: false,
aspect: [4, 3],
quality: 1,
exif: true,  // Request EXIF data
});

if (pickerResult.canceled) {
return;
}

const pickedAsset = pickerResult.assets[0];

if (pickedAsset) {
console.log("Picked image URI:", pickedAsset.uri);
console.log("Exif data available:", pickedAsset.exif ? "Yes"  : "No");

function dmsToDecimal(dms, ref) {
const [degrees, minutes, seconds] = dms;
let decimal = degrees + minutes / 60 + seconds / 3600;
if (ref === 'S' || ref === 'W') {
decimal = -decimal;
}
return decimal;
}

let location = null;

if (pickedAsset.exif &&
pickedAsset.exif.GPSLatitude !== undefined &&
pickedAsset.exif.GPSLongitude !== undefined) {

let latitude = pickedAsset.exif.GPSLatitude;
let longitude = pickedAsset.exif.GPSLongitude;
console.log(pickedAsset.exif);
console.log(pickedAsset.exif.GPSLatitude);
console.log(pickedAsset.exif.GPSLongitude);

// Handle potential DMS array format
if (Array.isArray(latitude) && Array.isArray(longitude)) {
const latRef = pickedAsset.exif.GPSLatitudeRef || 'N';
const lonRef = pickedAsset.exif.GPSLongitudeRef || 'E';
latitude = dmsToDecimal(latitude, latRef);
longitude = dmsToDecimal(longitude, lonRef);
}

console.log("Found location in EXIF data:", {
latitude,
longitude
});

location = {
latitude,
longitude
};
}

// Second attempt: Try to find location metadata using our helper function
if (!location) {
console.log("No EXIF location found, trying alternative methods...");
location = await tryGetImageLocation(pickedAsset.uri);
}

// If we found location data, create the marker
if (location) {
console.log("Successfully found location data:", location);

const newMarker = {
id: pickedAsset.uri,
uri: pickedAsset.uri,
latitude: location.latitude,
longitude: location.longitude,
};

// Add the marker
setMarkers(prevMarkers => [...prevMarkers, newMarker]);

// Focus map on the new marker
setMapRegion({
latitude: location.latitude,
longitude: location.longitude,
latitudeDelta: 0.01,
longitudeDelta: 0.01,
});

Alert.alert(
"Success",
"Image added to map with its original location data!"
);
} else {
// No location data found, offer manual placement
console.log("No location data found, offering manual placement options");

Alert.alert(
"No Location Data",
"This image doesn't have location data.  How would you like to place it?",
[
{
text: "Use My Current Location",
onPress: () => {
// Create marker at current location
const newMarker = {
id: pickedAsset.uri,
uri: pickedAsset.uri,
latitude: currentLocation.latitude,
longitude: currentLocation.longitude,
};

// Add the new marker
setMarkers(prevMarkers => [...prevMarkers, newMarker]);

// Focus map on the new marker
setMapRegion({
latitude: currentLocation.latitude,
longitude: currentLocation.longitude,
latitudeDelta: 0.01,
longitudeDelta: 0.01,
});
}
},
{
text: "Tap on Map to Place",
onPress: () => {
// Enter manual location mode
setPendingImage(pickedAsset);
setManualLocationMode(true);

// Show instructions
Alert.alert(
"Tap on Map",
"Tap anywhere on the map to place your image at that location."
);
}
},
{
text: "Cancel",
style: "cancel"
}
]
);
}
}
};

return (


{markers.map((marker) => (
 openModal(marker)}
>


))}


{/* Modal for Full-Screen Image */}
{selectedImage && (



Close




)}

{/* Loading indicator */}
{isLoading && (

Loading...

)}

{/* Button to Add Image from Library */}

Add Image


{/* Instruction banner during manual placement mode */}
{manualLocationMode && (

Tap anywhere on the map to place your image
  {
setManualLocationMode(false);
setPendingImage(null);
}}
>
Cancel


)}

);
}

const styles = StyleSheet.create({
container: {
flex: 1
},
map: {
flex: 1
},
markerImage: {
width: 40,
height: 40,
borderRadius: 5,
borderWidth: 2,
borderColor: 'white'
},
modalContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'black',
},
modalImage: {
width: '100%',
height: '90%',
},
closeButton: {
position: 'absolute',
top: 40,
left: 20,
zIndex: 1,
padding: 10,
backgroundColor: 'rgba(0,0,0,0.5)',
borderRadius: 5,
},
closeText: {
color: 'white',
fontSize: 18,
},
addButton: {
position: 'absolute',
bottom: 30,
left: 20,
padding: 15,
backgroundColor: '#007BFF',
borderRadius: 10,
elevation: 3,
},
addButtonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
banner: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0,123,255,0.8)',
padding: 15,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
bannerText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
cancelButton: {
backgroundColor: '#FFF',
paddingVertical: 5,
paddingHorizontal: 10,
borderRadius: 5,
},
cancelText: {
color: '#007BFF',
fontWeight: 'bold',
},
loadingOverlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0,0,0,0.5)',
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
color: 'white',
fontSize: 18,
fontWeight: 'bold',
}
});

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post