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.