Cihaz Özelliklerine Erişim Nedir? React Native uygulamaları, cihazın native özelliklerine erişebilir. Bu özellikler arasında kamera, konum servisleri, bildirimler, sensörler, dosya sistemi ve daha fazlası bulunur. Bu derste bu özellikleri nasıl kullanacağınızı öğreneceksiniz.
Erişilebilir Cihaz Özellikleri: Kamera: Fotoğraf çekme ve video kaydetmeKonum: GPS ve ağ tabanlı konumBildirimler: Push ve local bildirimlerSensörler: Accelerometer, gyroscope, magnetometerDosya Sistemi: Dosya okuma/yazmaKişiler: Telefon rehberi erişimiTakvim: Etkinlik ekleme/okuma⚠️ Önemli: Cihaz özelliklerine erişim için kullanıcıdan izin almanız gerekir. iOS ve Android'de farklı izin sistemleri vardır.
Kamera ve Medya Erişimi Expo Camera API'si ile kamera erişimi ve fotoğraf/video çekme işlemlerini gerçekleştirebilirsiniz:
Kopyala // Expo Camera kurulumu npx expo install expo-camera expo-media-library // Kamera bileşeni import React, { useState, useEffect, useRef } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, Alert } from 'react-native'; import { Camera } from 'expo-camera'; import * as MediaLibrary from 'expo-media-library'; const CameraApp = () => { const [hasPermission, setHasPermission] = useState(null); const [type, setType] = useState(Camera.Constants.Type.back); const [flashMode, setFlashMode] = useState(Camera.Constants.FlashMode.off); const cameraRef = useRef(null); // İzinleri kontrol et useEffect(() => { (async () => { const { status } = await Camera.requestCameraPermissionsAsync(); const mediaLibraryStatus = await MediaLibrary.requestPermissionsAsync(); setHasPermission(status === 'granted' && mediaLibraryStatus.status === 'granted'); })(); }, []); // Fotoğraf çek const takePicture = async () => { if (cameraRef.current) { try { const photo = await cameraRef.current.takePictureAsync({ quality: 0.8, base64: false, exif: false, }); // Fotoğrafı galerie kaydet await MediaLibrary.saveToLibraryAsync(photo.uri); Alert.alert('Başarılı', 'Fotoğraf galeriye kaydedildi'); } catch (error) { console.error('Fotoğraf çekme hatası:', error); Alert.alert('Hata', 'Fotoğraf çekilemedi'); } } }; // Video kaydet const recordVideo = async () => { if (cameraRef.current) { try { const video = await cameraRef.current.recordAsync({ quality: Camera.Constants.VideoQuality['720p'], maxDuration: 30, // 30 saniye }); await MediaLibrary.saveToLibraryAsync(video.uri); Alert.alert('Başarılı', 'Video galeriye kaydedildi'); } catch (error) { console.error('Video kaydetme hatası:', error); Alert.alert('Hata', 'Video kaydedilemedi'); } } }; // Video kaydını durdur const stopRecording = () => { if (cameraRef.current) { cameraRef.current.stopRecording(); } }; if (hasPermission === null) { return <Text>Kamera izni kontrol ediliyor...</Text>; } if (hasPermission === false) { return <Text>Kamera erişimi reddedildi</Text>; } return ( <View style={styles.container}> <Camera style={styles.camera} type={type} flashMode={flashMode} ref={cameraRef} > <View style={styles.buttonContainer}> {/* Kamera değiştir */} <TouchableOpacity style={styles.button} onPress={() => { setType( type === Camera.Constants.Type.back ? Camera.Constants.Type.front : Camera.Constants.Type.back ); }} > <Text style={styles.text}>Kamerayı Çevir</Text> </TouchableOpacity> {/* Flash değiştir */} <TouchableOpacity style={styles.button} onPress={() => { setFlashMode( flashMode === Camera.Constants.FlashMode.off ? Camera.Constants.FlashMode.on : Camera.Constants.FlashMode.off ); }} > <Text style={styles.text}> Flash: {flashMode === Camera.Constants.FlashMode.off ? 'Kapalı' : 'Açık'} </Text> </TouchableOpacity> {/* Fotoğraf çek */} <TouchableOpacity style={styles.captureButton} onPress={takePicture}> <Text style={styles.text}>📷</Text> </TouchableOpacity> {/* Video kaydet */} <TouchableOpacity style={styles.recordButton} onPress={recordVideo}> <Text style={styles.text}>🎥</Text> </TouchableOpacity> </View> </Camera> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, }, camera: { flex: 1, }, buttonContainer: { flex: 1, backgroundColor: 'transparent', flexDirection: 'row', justifyContent: 'space-around', alignItems: 'flex-end', paddingBottom: 50, }, button: { backgroundColor: 'rgba(0,0,0,0.5)', padding: 15, borderRadius: 5, }, captureButton: { backgroundColor: 'rgba(255,255,255,0.3)', width: 70, height: 70, borderRadius: 35, justifyContent: 'center', alignItems: 'center', }, recordButton: { backgroundColor: 'rgba(255,0,0,0.7)', width: 70, height: 70, borderRadius: 35, justifyContent: 'center', alignItems: 'center', }, text: { fontSize: 18, color: 'white', fontWeight: 'bold', }, }); export default CameraApp;
Kamera Simülasyonu 📷 Fotoğraf Çek 🎥 Video Kaydet 🔄 Kamerayı Çevir ⚡ Flash Aç/Kapat
Konum Servisleri Expo Location API'si ile kullanıcının konumunu alabilir ve konum takibi yapabilirsiniz:
Kopyala // Expo Location kurulumu npx expo install expo-location // Konum bileşeni import React, { useState, useEffect } from 'react'; import { View, Text, Button, StyleSheet, Alert } from 'react-native'; import * as Location from 'expo-location'; const LocationApp = () => { const [location, setLocation] = useState(null); const [address, setAddress] = useState(null); const [watching, setWatching] = useState(false); const [subscription, setSubscription] = useState(null); // Konum izni al const requestLocationPermission = async () => { try { const { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { Alert.alert('Hata', 'Konum izni reddedildi'); return false; } return true; } catch (error) { console.error('Konum izni hatası:', error); return false; } }; // Mevcut konumu al const getCurrentLocation = async () => { const hasPermission = await requestLocationPermission(); if (!hasPermission) return; try { const currentLocation = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High, }); setLocation(currentLocation); // Adres bilgisini al (reverse geocoding) const addressInfo = await Location.reverseGeocodeAsync({ latitude: currentLocation.coords.latitude, longitude: currentLocation.coords.longitude, }); setAddress(addressInfo[0]); } catch (error) { console.error('Konum alma hatası:', error); Alert.alert('Hata', 'Konum alınamadı'); } }; // Konum takibini başlat const startLocationTracking = async () => { const hasPermission = await requestLocationPermission(); if (!hasPermission) return; try { const locationSubscription = await Location.watchPositionAsync( { accuracy: Location.Accuracy.High, timeInterval: 5000, // 5 saniyede bir güncelle distanceInterval: 10, // 10 metre hareket ettiğinde güncelle }, (newLocation) => { setLocation(newLocation); console.log('Yeni konum:', newLocation); } ); setSubscription(locationSubscription); setWatching(true); } catch (error) { console.error('Konum takibi hatası:', error); Alert.alert('Hata', 'Konum takibi başlatılamadı'); } }; // Konum takibini durdur const stopLocationTracking = () => { if (subscription) { subscription.remove(); setSubscription(null); setWatching(false); } }; // Adres arama (geocoding) const searchAddress = async (searchText) => { try { const results = await Location.geocodeAsync(searchText); if (results.length > 0) { const result = results[0]; setLocation({ coords: { latitude: result.latitude, longitude: result.longitude, } }); // Adres bilgisini al const addressInfo = await Location.reverseGeocodeAsync({ latitude: result.latitude, longitude: result.longitude, }); setAddress(addressInfo[0]); } else { Alert.alert('Hata', 'Adres bulunamadı'); } } catch (error) { console.error('Adres arama hatası:', error); Alert.alert('Hata', 'Adres aranamadı'); } }; // Bileşen temizlendiğinde takibi durdur useEffect(() => { return () => { if (subscription) { subscription.remove(); } }; }, [subscription]); return ( <View style={styles.container}> <Text style={styles.title}>Konum Servisleri</Text> <View style={styles.buttonContainer}> <Button title="Mevcut Konumu Al" onPress={getCurrentLocation} /> {!watching ? ( <Button title="Konum Takibini Başlat" onPress={startLocationTracking} /> ) : ( <Button title="Konum Takibini Durdur" onPress={stopLocationTracking} color="#e74c3c" /> )} </View> {location && ( <View style={styles.locationInfo}> <Text style={styles.sectionTitle}>Konum Bilgileri</Text> <Text>Enlem: {location.coords.latitude.toFixed(6)}</Text> <Text>Boylam: {location.coords.longitude.toFixed(6)}</Text> <Text>Doğruluk: {location.coords.accuracy?.toFixed(2)} metre</Text> <Text>Hız: {location.coords.speed?.toFixed(2) || 0} m/s</Text> <Text>Yükseklik: {location.coords.altitude?.toFixed(2) || 'Bilinmiyor'} metre</Text> </View> )} {address && ( <View style={styles.addressInfo}> <Text style={styles.sectionTitle}>Adres Bilgileri</Text> <Text>Sokak: {address.street || 'Bilinmiyor'}</Text> <Text>Şehir: {address.city || 'Bilinmiyor'}</Text> <Text>Bölge: {address.region || 'Bilinmiyor'}</Text> <Text>Ülke: {address.country || 'Bilinmiyor'}</Text> <Text>Posta Kodu: {address.postalCode || 'Bilinmiyor'}</Text> </View> )} {watching && ( <View style={styles.trackingStatus}> <Text style={styles.trackingText}>🔴 Konum takibi aktif</Text> </View> )} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, backgroundColor: '#f8f9fa', }, title: { fontSize: 24, fontWeight: 'bold', textAlign: 'center', marginBottom: 20, color: '#2c3e50', }, buttonContainer: { gap: 10, marginBottom: 20, }, locationInfo: { backgroundColor: 'white', padding: 15, borderRadius: 8, marginBottom: 15, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 3.84, elevation: 5, }, addressInfo: { backgroundColor: '#e8f4fd', padding: 15, borderRadius: 8, marginBottom: 15, }, sectionTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 10, color: '#34495e', }, trackingStatus: { backgroundColor: '#f8d7da', padding: 10, borderRadius: 5, alignItems: 'center', }, trackingText: { color: '#721c24', fontWeight: 'bold', }, }); export default LocationApp;
Konum Simülasyonu 📍 Mevcut Konum 🔄 Konum Takibi ⏹️ Takibi Durdur
Konum bilgisi burada görünecek...
Push Bildirimleri Expo Notifications API'si ile push bildirimleri gönderebilir ve yerel bildirimler oluşturabilirsiniz:
Kopyala // Expo Notifications kurulumu npx expo install expo-notifications expo-device expo-constants // Bildirim bileşeni import React, { useState, useEffect, useRef } from 'react'; import { View, Text, Button, Platform, Alert } from 'react-native'; import * as Notifications from 'expo-notifications'; import * as Device from 'expo-device'; import Constants from 'expo-constants'; // Bildirim davranışını ayarla Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldShowAlert: true, shouldPlaySound: true, shouldSetBadge: false, }), }); const NotificationApp = () => { const [expoPushToken, setExpoPushToken] = useState(''); const [notification, setNotification] = useState(false); const notificationListener = useRef(); const responseListener = useRef(); // Push token al const registerForPushNotificationsAsync = async () => { let token; if (Platform.OS === 'android') { await Notifications.setNotificationChannelAsync('default', { name: 'default', importance: Notifications.AndroidImportance.MAX, vibrationPattern: [0, 250, 250, 250], lightColor: '#FF231F7C', }); } if (Device.isDevice) { const { status: existingStatus } = await Notifications.getPermissionsAsync(); let finalStatus = existingStatus; if (existingStatus !== 'granted') { const { status } = await Notifications.requestPermissionsAsync(); finalStatus = status; } if (finalStatus !== 'granted') { Alert.alert('Hata', 'Bildirim izni reddedildi'); return; } token = (await Notifications.getExpoPushTokenAsync({ projectId: Constants.expoConfig.extra.eas.projectId, })).data; } else { Alert.alert('Hata', 'Push bildirimleri sadece fiziksel cihazlarda çalışır'); } return token; }; // Yerel bildirim gönder const sendLocalNotification = async () => { await Notifications.scheduleNotificationAsync({ content: { title: "Yerel Bildirim 📬", body: 'Bu bir yerel bildirimdir!', data: { data: 'goes here' }, }, trigger: { seconds: 2 }, }); }; // Zamanlanmış bildirim const scheduleNotification = async () => { await Notifications.scheduleNotificationAsync({ content: { title: "Zamanlanmış Bildirim ⏰", body: '5 saniye sonra gelecek bildirim!', data: { type: 'scheduled' }, }, trigger: { seconds: 5 }, }); Alert.alert('Başarılı', '5 saniye sonra bildirim gelecek'); }; // Günlük bildirim const scheduleDailyNotification = async () => { await Notifications.scheduleNotificationAsync({ content: { title: "Günlük Hatırlatma 📅", body: 'Günlük görevlerinizi kontrol etmeyi unutmayın!', data: { type: 'daily' }, }, trigger: { hour: 9, minute: 0, repeats: true, }, }); Alert.alert('Başarılı', 'Günlük bildirim ayarlandı (09:00)'); }; // Push bildirim gönder (test) const sendPushNotification = async () => { if (!expoPushToken) { Alert.alert('Hata', 'Push token bulunamadı'); return; } const message = { to: expoPushToken, sound: 'default', title: 'Push Bildirim 🚀', body: 'Bu bir push bildirimidir!', data: { someData: 'goes here' }, }; try { await fetch('https://exp.host/--/api/v2/push/send', { method: 'POST', headers: { Accept: 'application/json', 'Accept-encoding': 'gzip, deflate', 'Content-Type': 'application/json', }, body: JSON.stringify(message), }); Alert.alert('Başarılı', 'Push bildirim gönderildi'); } catch (error) { console.error('Push bildirim hatası:', error); Alert.alert('Hata', 'Push bildirim gönderilemedi'); } }; // Tüm zamanlanmış bildirimleri iptal et const cancelAllNotifications = async () => { await Notifications.cancelAllScheduledNotificationsAsync(); Alert.alert('Başarılı', 'Tüm zamanlanmış bildirimler iptal edildi'); }; useEffect(() => { registerForPushNotificationsAsync().then(token => setExpoPushToken(token)); // Bildirim dinleyicileri notificationListener.current = Notifications.addNotificationReceivedListener(notification => { setNotification(notification); }); responseListener.current = Notifications.addNotificationResponseReceivedListener(response => { console.log('Bildirime tıklandı:', response); }); return () => { Notifications.removeNotificationSubscription(notificationListener.current); Notifications.removeNotificationSubscription(responseListener.current); }; }, []); return ( <View style={{ flex: 1, padding: 20 }}> <Text style={{ fontSize: 24, fontWeight: 'bold', textAlign: 'center', marginBottom: 20 }}> Bildirimler </Text> <View style={{ gap: 10, marginBottom: 20 }}> <Button title="Yerel Bildirim Gönder" onPress={sendLocalNotification} /> <Button title="5 Saniye Sonra Bildirim" onPress={scheduleNotification} /> <Button title="Günlük Bildirim Ayarla" onPress={scheduleDailyNotification} /> <Button title="Push Bildirim Gönder" onPress={sendPushNotification} /> <Button title="Tüm Bildirimleri İptal Et" onPress={cancelAllNotifications} color="#e74c3c" /> </View> {expoPushToken && ( <View style={{ backgroundColor: '#f0f0f0', padding: 10, borderRadius: 5, marginBottom: 20 }}> <Text style={{ fontWeight: 'bold' }}>Push Token:</Text> <Text style={{ fontSize: 12, fontFamily: 'monospace' }}>{expoPushToken}</Text> </View> )} {notification && ( <View style={{ backgroundColor: '#e8f4fd', padding: 15, borderRadius: 5 }}> <Text style={{ fontWeight: 'bold' }}>Son Bildirim:</Text> <Text>Başlık: {notification.request.content.title}</Text> <Text>İçerik: {notification.request.content.body}</Text> <Text>Veri: {JSON.stringify(notification.request.content.data)}</Text> </View> )} </View> ); }; export default NotificationApp;
Sensör Erişimi Expo Sensors API'si ile cihazın çeşitli sensörlerine erişebilirsiniz:
Kopyala // Expo Sensors kurulumu npx expo install expo-sensors // Sensör bileşeni import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import { Accelerometer, Gyroscope, Magnetometer, Barometer } from 'expo-sensors'; const SensorApp = () => { const [accelerometerData, setAccelerometerData] = useState({}); const [gyroscopeData, setGyroscopeData] = useState({}); const [magnetometerData, setMagnetometerData] = useState({}); const [barometerData, setBarometerData] = useState({}); useEffect(() => { // Accelerometer (İvmeölçer) const accelerometerSubscription = Accelerometer.addListener(accelerometerData => { setAccelerometerData(accelerometerData); }); Accelerometer.setUpdateInterval(100); // 100ms // Gyroscope (Jiroskop) const gyroscopeSubscription = Gyroscope.addListener(gyroscopeData => { setGyroscopeData(gyroscopeData); }); Gyroscope.setUpdateInterval(100); // Magnetometer (Manyetometre) const magnetometerSubscription = Magnetometer.addListener(magnetometerData => { setMagnetometerData(magnetometerData); }); Magnetometer.setUpdateInterval(100); // Barometer (Barometre) const barometerSubscription = Barometer.addListener(barometerData => { setBarometerData(barometerData); }); Barometer.setUpdateInterval(1000); // 1 saniye return () => { accelerometerSubscription && accelerometerSubscription.remove(); gyroscopeSubscription && gyroscopeSubscription.remove(); magnetometerSubscription && magnetometerSubscription.remove(); barometerSubscription && barometerSubscription.remove(); }; }, []); const round = (n) => { if (!n) return 0; return Math.floor(n * 100) / 100; }; return ( <View style={styles.container}> <Text style={styles.title}>Sensör Verileri</Text> <View style={styles.sensorContainer}> <Text style={styles.sensorTitle}>📱 İvmeölçer (Accelerometer)</Text> <Text>X: {round(accelerometerData.x)} m/s²</Text> <Text>Y: {round(accelerometerData.y)} m/s²</Text> <Text>Z: {round(accelerometerData.z)} m/s²</Text> </View> <View style={styles.sensorContainer}> <Text style={styles.sensorTitle}>🌀 Jiroskop (Gyroscope)</Text> <Text>X: {round(gyroscopeData.x)} rad/s</Text> <Text>Y: {round(gyroscopeData.y)} rad/s</Text> <Text>Z: {round(gyroscopeData.z)} rad/s</Text> </View> <View style={styles.sensorContainer}> <Text style={styles.sensorTitle}>🧭 Manyetometre (Magnetometer)</Text> <Text>X: {round(magnetometerData.x)} µT</Text> <Text>Y: {round(magnetometerData.y)} µT</Text> <Text>Z: {round(magnetometerData.z)} µT</Text> </View> <View style={styles.sensorContainer}> <Text style={styles.sensorTitle}>🌡️ Barometre (Barometer)</Text> <Text>Basınç: {round(barometerData.pressure)} hPa</Text> <Text>Yükseklik: {round(barometerData.relativeAltitude)} m</Text> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, backgroundColor: '#f8f9fa', }, title: { fontSize: 24, fontWeight: 'bold', textAlign: 'center', marginBottom: 20, color: '#2c3e50', }, sensorContainer: { backgroundColor: 'white', padding: 15, borderRadius: 8, marginBottom: 15, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 3.84, elevation: 5, }, sensorTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 10, color: '#34495e', }, }); export default SensorApp;
Sensör Simülasyonu 📱 İvmeölçer 🌀 Jiroskop 🧭 Manyetometre 🌡️ Barometre
📋 İzin Yönetimi Özellik iOS İzni Android İzni Kullanım Kamera NSCameraUsageDescription CAMERA Fotoğraf/video çekme Konum NSLocationWhenInUseUsageDescription ACCESS_FINE_LOCATION GPS konumu alma Bildirimler Otomatik Otomatik Push/local bildirimler Mikrofon NSMicrophoneUsageDescription RECORD_AUDIO Ses kaydetme Kişiler NSContactsUsageDescription READ_CONTACTS Rehber erişimi
Sonraki Adımlar Bu derste cihaz özelliklerine erişimi öğrendiniz. Bir sonraki derste performans optimizasyonu konusunu ele alacak ve uygulamanızı nasıl hızlandıracağınızı öğreneceksiniz.
Bu Derste Öğrendikleriniz: Kamera ve medya erişimi Konum servisleri ve GPS Push ve yerel bildirimler Sensör verilerine erişim İzin yönetimi Native özellik entegrasyonu