Explore browser device APIs including Geolocation, Camera, Microphone, and more. Learn to build location-aware and device-integrated applications.
Modern browsers provide powerful APIs to access device capabilities like location, camera, microphone, and sensors. These APIs enable rich, interactive experiences while maintaining user privacy and security through permission systems.
The Geolocation API allows web applications to access the user's location information with their permission.
Basic Geolocation Usage:
1// Check if geolocation is supported
2if ('geolocation' in navigator) {
3 console.log('Geolocation is supported');
4} else {
5 console.log('Geolocation is not supported');
6}
7
8// Get current position
9navigator.geolocation.getCurrentPosition(
10 function(position) {
11 const latitude = position.coords.latitude;
12 const longitude = position.coords.longitude;
13 const accuracy = position.coords.accuracy;
14
15 console.log('Latitude:', latitude);
16 console.log('Longitude:', longitude);
17 console.log('Accuracy:', accuracy + ' meters');
18 },
19 function(error) {
20 console.error('Geolocation error:', error.message);
21 },
22 {
23 enableHighAccuracy: true,
24 timeout: 10000,
25 maximumAge: 300000 // 5 minutes
26 }
27);Comprehensive Geolocation Manager:
1class GeolocationManager {
2 constructor(options = {}) {
3 this.defaultOptions = {
4 enableHighAccuracy: true,
5 timeout: 10000,
6 maximumAge: 300000 // 5 minutes
7 };
8 this.options = { ...this.defaultOptions, ...options };
9 this.watchId = null;
10 }
11
12 // Check if geolocation is available
13 isSupported() {
14 return 'geolocation' in navigator;
15 }
16
17 // Get current position once
18 async getCurrentPosition() {
19 if (!this.isSupported()) {
20 throw new Error('Geolocation is not supported');
21 }
22
23 return new Promise((resolve, reject) => {
24 navigator.geolocation.getCurrentPosition(
25 (position) => {
26 resolve(this.formatPosition(position));
27 },
28 (error) => {
29 reject(this.handleError(error));
30 },
31 this.options
32 );
33 });
34 }
35
36 // Watch position changes
37 watchPosition(callback, errorCallback) {
38 if (!this.isSupported()) {
39 throw new Error('Geolocation is not supported');
40 }
41
42 this.watchId = navigator.geolocation.watchPosition(
43 (position) => {
44 callback(this.formatPosition(position));
45 },
46 (error) => {
47 if (errorCallback) {
48 errorCallback(this.handleError(error));
49 }
50 },
51 this.options
52 );
53
54 return this.watchId;
55 }
56
57 // Stop watching position
58 clearWatch() {
59 if (this.watchId !== null) {
60 navigator.geolocation.clearWatch(this.watchId);
61 this.watchId = null;
62 }
63 }
64
65 // Format position data
66 formatPosition(position) {
67 return {
68 latitude: position.coords.latitude,
69 longitude: position.coords.longitude,
70 accuracy: position.coords.accuracy,
71 altitude: position.coords.altitude,
72 altitudeAccuracy: position.coords.altitudeAccuracy,
73 heading: position.coords.heading,
74 speed: position.coords.speed,
75 timestamp: new Date(position.timestamp)
76 };
77 }
78
79 // Handle geolocation errors
80 handleError(error) {
81 const errorMessages = {
82 1: 'Permission denied - User denied the request for Geolocation',
83 2: 'Position unavailable - Location information is unavailable',
84 3: 'Timeout - The request to get user location timed out'
85 };
86
87 return {
88 code: error.code,
89 message: errorMessages[error.code] || 'Unknown error occurred'
90 };
91 }
92
93 // Calculate distance between two points
94 calculateDistance(lat1, lon1, lat2, lon2) {
95 const R = 6371; // Radius of the Earth in kilometers
96 const dLat = this.toRadians(lat2 - lat1);
97 const dLon = this.toRadians(lon2 - lon1);
98 const a =
99 Math.sin(dLat/2) * Math.sin(dLat/2) +
100 Math.cos(this.toRadians(lat1)) * Math.cos(this.toRadians(lat2)) *
101 Math.sin(dLon/2) * Math.sin(dLon/2);
102 const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
103 const distance = R * c; // Distance in kilometers
104 return distance;
105 }
106
107 toRadians(degrees) {
108 return degrees * (Math.PI/180);
109 }
110}
111
112// Usage
113const geoManager = new GeolocationManager({
114 enableHighAccuracy: true,
115 timeout: 15000
116});
117
118// Get current position
119try {
120 const position = await geoManager.getCurrentPosition();
121 console.log('Current position:', position);
122} catch (error) {
123 console.error('Geolocation error:', error);
124}
125
126// Watch position changes
127const watchId = geoManager.watchPosition(
128 (position) => {
129 console.log('Position updated:', position);
130 },
131 (error) => {
132 console.error('Watch error:', error);
133 }
134);
135
136// Stop watching after 1 minute
137setTimeout(() => {
138 geoManager.clearWatch();
139}, 60000);Browser Media APIs provide access to camera, microphone, and screen sharing capabilities.
Camera Access with getUserMedia:
1class CameraManager {
2 constructor() {
3 this.stream = null;
4 this.constraints = {
5 video: {
6 width: { ideal: 1280 },
7 height: { ideal: 720 },
8 facingMode: 'user' // 'user' for front camera, 'environment' for back
9 },
10 audio: false
11 };
12 }
13
14 // Check if getUserMedia is supported
15 isSupported() {
16 return navigator.mediaDevices && navigator.mediaDevices.getUserMedia;
17 }
18
19 // Start camera
20 async startCamera(videoElement, constraints = this.constraints) {
21 if (!this.isSupported()) {
22 throw new Error('getUserMedia is not supported');
23 }
24
25 try {
26 this.stream = await navigator.mediaDevices.getUserMedia(constraints);
27
28 if (videoElement) {
29 videoElement.srcObject = this.stream;
30 videoElement.play();
31 }
32
33 return this.stream;
34 } catch (error) {
35 throw this.handleMediaError(error);
36 }
37 }
38
39 // Stop camera
40 stopCamera() {
41 if (this.stream) {
42 this.stream.getTracks().forEach(track => {
43 track.stop();
44 });
45 this.stream = null;
46 }
47 }
48
49 // Take photo
50 takePhoto(videoElement, canvasElement) {
51 if (!this.stream || !videoElement) {
52 throw new Error('Camera not started or video element not provided');
53 }
54
55 const canvas = canvasElement || document.createElement('canvas');
56 const context = canvas.getContext('2d');
57
58 // Set canvas dimensions to match video
59 canvas.width = videoElement.videoWidth;
60 canvas.height = videoElement.videoHeight;
61
62 // Draw video frame to canvas
63 context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
64
65 // Return image data
66 return {
67 dataURL: canvas.toDataURL('image/jpeg', 0.8),
68 blob: new Promise(resolve => canvas.toBlob(resolve, 'image/jpeg', 0.8))
69 };
70 }
71
72 // Switch camera (front/back)
73 async switchCamera() {
74 const currentFacingMode = this.constraints.video.facingMode;
75 const newFacingMode = currentFacingMode === 'user' ? 'environment' : 'user';
76
77 this.constraints.video.facingMode = newFacingMode;
78
79 this.stopCamera();
80 return this.startCamera(null, this.constraints);
81 }
82
83 // Get available cameras
84 async getAvailableCameras() {
85 if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
86 throw new Error('Device enumeration not supported');
87 }
88
89 const devices = await navigator.mediaDevices.enumerateDevices();
90 return devices.filter(device => device.kind === 'videoinput');
91 }
92
93 handleMediaError(error) {
94 const errorMessages = {
95 'NotAllowedError': 'Permission denied - User denied camera access',
96 'NotFoundError': 'No camera found on this device',
97 'NotReadableError': 'Camera is already in use by another application',
98 'OverconstrainedError': 'Camera constraints cannot be satisfied',
99 'SecurityError': 'Security error - HTTPS required for camera access',
100 'TypeError': 'Invalid constraints provided'
101 };
102
103 return {
104 name: error.name,
105 message: errorMessages[error.name] || error.message
106 };
107 }
108}
109
110// Usage
111const camera = new CameraManager();
112
113// HTML elements
114const videoElement = document.getElementById('video');
115const captureButton = document.getElementById('capture');
116const canvasElement = document.getElementById('canvas');
117
118// Start camera
119async function startCamera() {
120 try {
121 await camera.startCamera(videoElement);
122 console.log('Camera started successfully');
123 } catch (error) {
124 console.error('Camera error:', error);
125 }
126}
127
128// Capture photo
129captureButton.addEventListener('click', () => {
130 try {
131 const photo = camera.takePhoto(videoElement, canvasElement);
132 console.log('Photo captured:', photo.dataURL);
133 } catch (error) {
134 console.error('Capture error:', error);
135 }
136});
137
138// Start camera when page loads
139startCamera();Screen Sharing API:
1class ScreenShareManager {
2 constructor() {
3 this.stream = null;
4 }
5
6 // Check if screen sharing is supported
7 isSupported() {
8 return navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia;
9 }
10
11 // Start screen sharing
12 async startScreenShare(videoElement, options = {}) {
13 if (!this.isSupported()) {
14 throw new Error('Screen sharing is not supported');
15 }
16
17 const constraints = {
18 video: {
19 cursor: options.cursor || 'always',
20 displaySurface: options.displaySurface || 'monitor'
21 },
22 audio: options.audio || false
23 };
24
25 try {
26 this.stream = await navigator.mediaDevices.getDisplayMedia(constraints);
27
28 if (videoElement) {
29 videoElement.srcObject = this.stream;
30 videoElement.play();
31 }
32
33 // Listen for user stopping the share
34 this.stream.getVideoTracks()[0].addEventListener('ended', () => {
35 console.log('Screen sharing stopped by user');
36 this.stopScreenShare();
37 });
38
39 return this.stream;
40 } catch (error) {
41 throw new Error('Screen sharing permission denied or failed');
42 }
43 }
44
45 // Stop screen sharing
46 stopScreenShare() {
47 if (this.stream) {
48 this.stream.getTracks().forEach(track => {
49 track.stop();
50 });
51 this.stream = null;
52 }
53 }
54}
55
56// Usage
57const screenShare = new ScreenShareManager();
58
59async function startScreenSharing() {
60 try {
61 const videoElement = document.getElementById('screen-video');
62 await screenShare.startScreenShare(videoElement, {
63 audio: true,
64 cursor: 'always'
65 });
66 console.log('Screen sharing started');
67 } catch (error) {
68 console.error('Screen sharing error:', error);
69 }
70}Modern devices provide various sensors and capabilities that web applications can access.
Device Orientation and Motion:
1class DeviceSensorManager {
2 constructor() {
3 this.orientationSupported = 'DeviceOrientationEvent' in window;
4 this.motionSupported = 'DeviceMotionEvent' in window;
5 this.permissionGranted = false;
6 }
7
8 // Request permission for iOS 13+
9 async requestPermission() {
10 if (typeof DeviceOrientationEvent.requestPermission === 'function') {
11 try {
12 const permission = await DeviceOrientationEvent.requestPermission();
13 this.permissionGranted = permission === 'granted';
14 return this.permissionGranted;
15 } catch (error) {
16 console.error('Permission request failed:', error);
17 return false;
18 }
19 }
20 // For non-iOS devices, assume permission is granted
21 this.permissionGranted = true;
22 return true;
23 }
24
25 // Listen to device orientation
26 startOrientationTracking(callback) {
27 if (!this.orientationSupported) {
28 throw new Error('Device orientation not supported');
29 }
30
31 if (!this.permissionGranted) {
32 throw new Error('Permission not granted for device orientation');
33 }
34
35 const handleOrientation = (event) => {
36 callback({
37 alpha: event.alpha, // Rotation around z-axis (0-360 degrees)
38 beta: event.beta, // Rotation around x-axis (-180 to 180 degrees)
39 gamma: event.gamma, // Rotation around y-axis (-90 to 90 degrees)
40 absolute: event.absolute
41 });
42 };
43
44 window.addEventListener('deviceorientation', handleOrientation);
45
46 return () => {
47 window.removeEventListener('deviceorientation', handleOrientation);
48 };
49 }
50
51 // Listen to device motion
52 startMotionTracking(callback) {
53 if (!this.motionSupported) {
54 throw new Error('Device motion not supported');
55 }
56
57 const handleMotion = (event) => {
58 callback({
59 acceleration: {
60 x: event.acceleration.x,
61 y: event.acceleration.y,
62 z: event.acceleration.z
63 },
64 accelerationIncludingGravity: {
65 x: event.accelerationIncludingGravity.x,
66 y: event.accelerationIncludingGravity.y,
67 z: event.accelerationIncludingGravity.z
68 },
69 rotationRate: {
70 alpha: event.rotationRate.alpha,
71 beta: event.rotationRate.beta,
72 gamma: event.rotationRate.gamma
73 },
74 interval: event.interval
75 });
76 };
77
78 window.addEventListener('devicemotion', handleMotion);
79
80 return () => {
81 window.removeEventListener('devicemotion', handleMotion);
82 };
83 }
84}
85
86// Usage
87const sensorManager = new DeviceSensorManager();
88
89// Request permission first (especially for iOS)
90async function initializeSensors() {
91 const permissionGranted = await sensorManager.requestPermission();
92
93 if (!permissionGranted) {
94 console.error('Permission denied for device sensors');
95 return;
96 }
97
98 // Track device orientation
99 const stopOrientationTracking = sensorManager.startOrientationTracking((data) => {
100 console.log('Orientation:', data);
101 // Update UI based on device orientation
102 updateCompass(data.alpha);
103 });
104
105 // Track device motion
106 const stopMotionTracking = sensorManager.startMotionTracking((data) => {
107 console.log('Motion:', data);
108 // Detect shake gesture
109 detectShake(data.accelerationIncludingGravity);
110 });
111}
112
113// Compass implementation
114function updateCompass(heading) {
115 const compass = document.getElementById('compass');
116 if (compass && heading !== null) {
117 compass.style.transform = `rotate(${-heading}deg)`;
118 }
119}
120
121// Shake detection
122let lastShakeTime = 0;
123function detectShake(acceleration) {
124 const threshold = 15; // Adjust sensitivity
125 const timeDiff = 100; // Minimum time between shakes
126
127 const totalAcceleration = Math.sqrt(
128 acceleration.x * acceleration.x +
129 acceleration.y * acceleration.y +
130 acceleration.z * acceleration.z
131 );
132
133 const now = Date.now();
134 if (totalAcceleration > threshold && now - lastShakeTime > timeDiff) {
135 console.log('Shake detected!');
136 lastShakeTime = now;
137 // Handle shake event
138 onShakeDetected();
139 }
140}
141
142function onShakeDetected() {
143 // Implement shake response
144 document.body.style.backgroundColor = `hsl(${Math.random() * 360}, 70%, 80%)`;
145}Battery Status API (deprecated but educational):
1// Note: Battery Status API is deprecated for privacy reasons
2// This is for educational purposes only
3
4class BatteryManager {
5 constructor() {
6 this.battery = null;
7 }
8
9 async getBatteryInfo() {
10 if ('getBattery' in navigator) {
11 try {
12 this.battery = await navigator.getBattery();
13 return {
14 charging: this.battery.charging,
15 chargingTime: this.battery.chargingTime,
16 dischargingTime: this.battery.dischargingTime,
17 level: this.battery.level
18 };
19 } catch (error) {
20 throw new Error('Battery API not available');
21 }
22 } else {
23 throw new Error('Battery API not supported');
24 }
25 }
26
27 // Listen for battery events
28 addBatteryListeners(callbacks = {}) {
29 if (!this.battery) {
30 throw new Error('Battery not initialized');
31 }
32
33 if (callbacks.onChargingChange) {
34 this.battery.addEventListener('chargingchange', () => {
35 callbacks.onChargingChange(this.battery.charging);
36 });
37 }
38
39 if (callbacks.onLevelChange) {
40 this.battery.addEventListener('levelchange', () => {
41 callbacks.onLevelChange(this.battery.level);
42 });
43 }
44 }
45}
46
47// Modern alternative: Use CSS media queries for power preferences
48function detectPowerPreference() {
49 // Detect if user prefers reduced performance for battery saving
50 if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
51 console.log('User prefers reduced motion - consider power-saving features');
52 }
53
54 // Detect connection speed to adjust features
55 if ('connection' in navigator) {
56 const connection = navigator.connection;
57 if (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g') {
58 console.log('Slow connection detected - optimize for performance');
59 }
60 }
61}Your progress is saved in this browser, on this device only.