Skip to content

Device Capabilities ​

Mini programs can access various device capabilities to create rich user experiences. This guide covers the most commonly used device APIs and best practices.

System Information ​

Getting Device Info ​

javascript
// Get system information
wx.getSystemInfo({
  success: (res) => {
    console.log('Device info:', {
      brand: res.brand,
      model: res.model,
      system: res.system,
      platform: res.platform,
      screenWidth: res.screenWidth,
      screenHeight: res.screenHeight,
      windowWidth: res.windowWidth,
      windowHeight: res.windowHeight,
      pixelRatio: res.pixelRatio,
      statusBarHeight: res.statusBarHeight,
      safeArea: res.safeArea
    })
  }
})

// Synchronous version
const systemInfo = wx.getSystemInfoSync()
console.log('System:', systemInfo.system)
console.log('Version:', systemInfo.version)

Safe Area Handling ​

javascript
// Handle safe area for different devices
Page({
  data: {
    safeAreaInsets: { top: 0, bottom: 0 }
  },
  
  onLoad() {
    const { safeArea, screenHeight, statusBarHeight } = wx.getSystemInfoSync()
    
    this.setData({
      safeAreaInsets: {
        top: safeArea.top,
        bottom: screenHeight - safeArea.bottom
      },
      statusBarHeight
    })
  }
})
css
/* CSS for safe area */
.safe-area-top {
  padding-top: var(--status-bar-height);
}

.safe-area-bottom {
  padding-bottom: env(safe-area-inset-bottom);
}

Camera & Media ​

Camera Access ​

javascript
// Take photo
wx.chooseImage({
  count: 1,
  sizeType: ['original', 'compressed'],
  sourceType: ['album', 'camera'],
  success: (res) => {
    const tempFilePaths = res.tempFilePaths
    console.log('Selected images:', tempFilePaths)
    
    // Display image
    this.setData({
      imagePath: tempFilePaths[0]
    })
  }
})

// Take photo directly
wx.chooseMedia({
  count: 1,
  mediaType: ['image'],
  sourceType: ['album', 'camera'],
  camera: 'back',
  success: (res) => {
    console.log('Media files:', res.tempFiles)
  }
})

Video Recording ​

javascript
// Record video
wx.chooseVideo({
  sourceType: ['album', 'camera'],
  maxDuration: 60,
  camera: 'back',
  success: (res) => {
    console.log('Video info:', {
      tempFilePath: res.tempFilePath,
      duration: res.duration,
      size: res.size,
      height: res.height,
      width: res.width
    })
  }
})

// Using chooseMedia for video
wx.chooseMedia({
  count: 1,
  mediaType: ['video'],
  sourceType: ['album', 'camera'],
  maxDuration: 30,
  success: (res) => {
    const media = res.tempFiles[0]
    console.log('Video selected:', media)
  }
})

Location Services ​

Getting Current Location ​

javascript
// Get current location
wx.getLocation({
  type: 'gcj02', // 'wgs84' | 'gcj02'
  success: (res) => {
    console.log('Location:', {
      latitude: res.latitude,
      longitude: res.longitude,
      speed: res.speed,
      accuracy: res.accuracy,
      altitude: res.altitude
    })
    
    // Use location data
    this.setData({
      userLocation: {
        latitude: res.latitude,
        longitude: res.longitude
      }
    })
  },
  fail: (err) => {
    console.error('Location access denied:', err)
    // Handle permission denial
    this.handleLocationError()
  }
})

Location Permission ​

javascript
// Check and request location permission
function requestLocationPermission() {
  return new Promise((resolve, reject) => {
    wx.getSetting({
      success: (res) => {
        if (res.authSetting['scope.userLocation']) {
          // Permission already granted
          resolve(true)
        } else {
          // Request permission
          wx.authorize({
            scope: 'scope.userLocation',
            success: () => resolve(true),
            fail: () => {
              // Show manual authorization dialog
              wx.showModal({
                title: 'Location Permission',
                content: 'Please enable location access in settings',
                confirmText: 'Settings',
                success: (modalRes) => {
                  if (modalRes.confirm) {
                    wx.openSetting()
                  }
                }
              })
              reject(false)
            }
          })
        }
      }
    })
  })
}

// Usage
Page({
  async getCurrentLocation() {
    try {
      await requestLocationPermission()
      wx.getLocation({
        type: 'gcj02',
        success: (res) => {
          console.log('Location obtained:', res)
        }
      })
    } catch (error) {
      console.log('Location permission denied')
    }
  }
})

Map Integration ​

html
<!-- Map component -->
<map
  id="map"
  longitude="{{longitude}}"
  latitude="{{latitude}}"
  scale="16"
  markers="{{markers}}"
  bindmarkertap="onMarkerTap"
  bindregionchange="onRegionChange"
  style="width: 100%; height: 300px;"
></map>
javascript
Page({
  data: {
    latitude: 39.908823,
    longitude: 116.397470,
    markers: [
      {
        id: 1,
        latitude: 39.908823,
        longitude: 116.397470,
        title: 'Current Location',
        iconPath: '/images/marker.png',
        width: 30,
        height: 30
      }
    ]
  },
  
  onMarkerTap(e) {
    console.log('Marker tapped:', e.detail.markerId)
  },
  
  onRegionChange(e) {
    if (e.type === 'end') {
      console.log('Region changed:', e.detail)
    }
  }
})

Sensors ​

Accelerometer ​

javascript
// Start accelerometer
wx.startAccelerometer({
  interval: 'normal', // 'game' | 'ui' | 'normal'
  success: () => {
    console.log('Accelerometer started')
  }
})

// Listen to accelerometer data
wx.onAccelerometerChange((res) => {
  console.log('Acceleration:', {
    x: res.x,
    y: res.y,
    z: res.z
  })
  
  // Detect shake gesture
  const acceleration = Math.sqrt(res.x * res.x + res.y * res.y + res.z * res.z)
  if (acceleration > 2) {
    console.log('Device shaken!')
    this.handleShakeGesture()
  }
})

// Stop accelerometer
wx.stopAccelerometer()

Compass ​

javascript
// Start compass
wx.startCompass({
  success: () => {
    console.log('Compass started')
  }
})

// Listen to compass data
wx.onCompassChange((res) => {
  console.log('Direction:', res.direction)
  
  // Update UI with direction
  this.setData({
    compassDirection: res.direction
  })
})

// Stop compass
wx.stopCompass()

Gyroscope ​

javascript
// Start gyroscope
wx.startGyroscope({
  interval: 'normal',
  success: () => {
    console.log('Gyroscope started')
  }
})

// Listen to gyroscope data
wx.onGyroscopeChange((res) => {
  console.log('Gyroscope:', {
    x: res.x, // rotation around x-axis
    y: res.y, // rotation around y-axis
    z: res.z  // rotation around z-axis
  })
})

// Stop gyroscope
wx.stopGyroscope()

Device Motion & Vibration ​

Vibration ​

javascript
// Short vibration
wx.vibrateShort({
  type: 'heavy', // 'heavy' | 'medium' | 'light'
  success: () => {
    console.log('Vibration triggered')
  }
})

// Long vibration
wx.vibrateLong({
  success: () => {
    console.log('Long vibration triggered')
  }
})

// Custom vibration pattern (Android only)
if (wx.canIUse('vibrateShort')) {
  // Vibrate in pattern: 200ms on, 100ms off, 200ms on
  setTimeout(() => wx.vibrateShort(), 0)
  setTimeout(() => wx.vibrateShort(), 300)
}

Screen Brightness ​

javascript
// Get screen brightness
wx.getScreenBrightness({
  success: (res) => {
    console.log('Current brightness:', res.value)
  }
})

// Set screen brightness
wx.setScreenBrightness({
  value: 0.8, // 0-1
  success: () => {
    console.log('Brightness set')
  }
})

// Keep screen on
wx.setKeepScreenOn({
  keepScreenOn: true,
  success: () => {
    console.log('Screen will stay on')
  }
})

Audio & Voice ​

Audio Recording ​

javascript
// Start recording
const recorderManager = wx.getRecorderManager()

recorderManager.onStart(() => {
  console.log('Recording started')
})

recorderManager.onStop((res) => {
  console.log('Recording stopped:', {
    tempFilePath: res.tempFilePath,
    duration: res.duration,
    fileSize: res.fileSize
  })
})

recorderManager.onError((res) => {
  console.error('Recording error:', res)
})

// Start recording
recorderManager.start({
  duration: 60000, // max 60 seconds
  sampleRate: 16000,
  numberOfChannels: 1,
  encodeBitRate: 96000,
  format: 'mp3'
})

// Stop recording
recorderManager.stop()

Audio Playback ​

javascript
// Create audio context
const audioContext = wx.createAudioContext('myAudio')

// Play audio
audioContext.play()

// Pause audio
audioContext.pause()

// Set current time
audioContext.seek(30) // seek to 30 seconds

// Using inner audio context for background audio
const innerAudioContext = wx.createInnerAudioContext()
innerAudioContext.src = 'https://example.com/audio.mp3'
innerAudioContext.autoplay = true

innerAudioContext.onPlay(() => {
  console.log('Audio started playing')
})

innerAudioContext.onError((res) => {
  console.error('Audio error:', res)
})

Bluetooth ​

Bluetooth Low Energy (BLE) ​

javascript
// Initialize Bluetooth adapter
wx.openBluetoothAdapter({
  success: () => {
    console.log('Bluetooth adapter opened')
    this.startBluetoothDevicesDiscovery()
  },
  fail: (err) => {
    console.error('Failed to open Bluetooth adapter:', err)
  }
})

// Start discovering devices
wx.startBluetoothDevicesDiscovery({
  allowDuplicatesKey: false,
  success: () => {
    console.log('Started discovering devices')
  }
})

// Listen for new devices
wx.onBluetoothDeviceFound((res) => {
  console.log('Found devices:', res.devices)
  
  res.devices.forEach(device => {
    if (device.name && device.name.includes('MyDevice')) {
      // Connect to specific device
      this.connectToDevice(device.deviceId)
    }
  })
})

// Connect to device
function connectToDevice(deviceId) {
  wx.createBLEConnection({
    deviceId,
    success: () => {
      console.log('Connected to device')
      // Get services
      wx.getBLEDeviceServices({
        deviceId,
        success: (res) => {
          console.log('Services:', res.services)
        }
      })
    }
  })
}

// Close Bluetooth adapter
wx.closeBluetoothAdapter()

File System ​

File Operations ​

javascript
// Get file system manager
const fs = wx.getFileSystemManager()

// Write file
fs.writeFile({
  filePath: `${wx.env.USER_DATA_PATH}/data.txt`,
  data: 'Hello World',
  encoding: 'utf8',
  success: () => {
    console.log('File written successfully')
  },
  fail: (err) => {
    console.error('Write file failed:', err)
  }
})

// Read file
fs.readFile({
  filePath: `${wx.env.USER_DATA_PATH}/data.txt`,
  encoding: 'utf8',
  success: (res) => {
    console.log('File content:', res.data)
  },
  fail: (err) => {
    console.error('Read file failed:', err)
  }
})

// Check if file exists
fs.access({
  path: `${wx.env.USER_DATA_PATH}/data.txt`,
  success: () => {
    console.log('File exists')
  },
  fail: () => {
    console.log('File does not exist')
  }
})

// Delete file
fs.unlink({
  filePath: `${wx.env.USER_DATA_PATH}/data.txt`,
  success: () => {
    console.log('File deleted')
  }
})

Best Practices ​

Permission Management ​

javascript
// Centralized permission manager
class PermissionManager {
  static async checkPermission(scope) {
    return new Promise((resolve) => {
      wx.getSetting({
        success: (res) => {
          resolve(res.authSetting[scope] === true)
        },
        fail: () => resolve(false)
      })
    })
  }
  
  static async requestPermission(scope, title, content) {
    const hasPermission = await this.checkPermission(scope)
    if (hasPermission) return true
    
    return new Promise((resolve) => {
      wx.authorize({
        scope,
        success: () => resolve(true),
        fail: () => {
          wx.showModal({
            title,
            content,
            confirmText: 'Settings',
            success: (res) => {
              if (res.confirm) {
                wx.openSetting()
              }
              resolve(false)
            }
          })
        }
      })
    })
  }
}

// Usage
Page({
  async useCamera() {
    const hasPermission = await PermissionManager.requestPermission(
      'scope.camera',
      'Camera Permission',
      'Please allow camera access to take photos'
    )
    
    if (hasPermission) {
      wx.chooseImage({
        sourceType: ['camera'],
        success: (res) => {
          console.log('Photo taken:', res.tempFilePaths)
        }
      })
    }
  }
})

Error Handling ​

javascript
// Robust device capability usage
function safeDeviceCall(apiCall, fallback) {
  return new Promise((resolve, reject) => {
    if (!wx.canIUse(apiCall.name)) {
      console.warn(`API ${apiCall.name} not supported`)
      if (fallback) {
        resolve(fallback())
      } else {
        reject(new Error('API not supported'))
      }
      return
    }
    
    apiCall.call({
      success: resolve,
      fail: (err) => {
        console.error(`${apiCall.name} failed:`, err)
        if (fallback) {
          resolve(fallback())
        } else {
          reject(err)
        }
      }
    })
  })
}

// Usage
Page({
  async getDeviceInfo() {
    try {
      const systemInfo = await safeDeviceCall(
        { name: 'getSystemInfo', call: wx.getSystemInfo },
        () => ({ platform: 'unknown' })
      )
      console.log('System info:', systemInfo)
    } catch (error) {
      console.error('Failed to get system info:', error)
    }
  }
})

Performance Optimization ​

javascript
// Debounce sensor data
function debounce(func, wait) {
  let timeout
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout)
      func(...args)
    }
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
  }
}

// Throttle accelerometer updates
const throttledAccelerometerHandler = debounce((data) => {
  console.log('Accelerometer data:', data)
  // Process data
}, 100) // Update every 100ms

wx.onAccelerometerChange(throttledAccelerometerHandler)

Device capabilities provide powerful ways to create engaging mini program experiences. Always handle permissions gracefully and provide fallbacks for unsupported features.

Connecting Multiple Platforms, Empowering Innovation