Skip to main content

How to detect when a phone is dropped in Expo (wrapper of React Native)

· 3 min read
CTO

I met a guy on a beach who thought it would be neat to have your phone respond when it was dropped.

I thought about it, and came up with a little project idea.

Overview

The idea is to detect when a phone has fallen, and once detected, play a sound and change the UI.

Try the demo

  1. To test it out on your phone, first download the Expo Go app; this allows me to share apps in development.
  2. Then goto the URL: https://snack.expo.dev/@magician11/github.com-magician11-detect-phone-drop
    • If you're visiting the URL from your phone, simply tap "Open with Expo Go"
    • If you're visiting the URL from your laptop, open the Expo Go app you just installed on your phone, tap "Scan QR code", and scan the QR barcode on the webpage.

Your Expo Go app should then load the app, and you'll know it's ready when you see the photo of a sloth 🦥

Then try drop your phone on a soft surface like a bed; so you don't actually damage it! 😁

Technical details

The full source code for this demo can be found here.

Accelerometer

The Expo Accelerometer docs are here.

Firstly we need to subscribe to changes in the accelerometer.

  // subscribe to accelerometer changes
useEffect(() => {
Accelerometer.setUpdateInterval(16);
setSubscription(Accelerometer.addListener(analyseChange));
return () => {
subscription && subscription.remove();
setSubscription(null);
};
}, []);

Here, on the component loading, we're setting to get updates every 16 milliseconds. Then setting what to do when a change occurs; call analyseChange. And then cleanup the component when it unloads.

const analyseChange = async update => {
const acceleration = Math.sqrt(
Math.pow(update.x, 2) + Math.pow(update.y, 2) + Math.pow(update.z, 2)
);

if (acceleration > 5.5) {
// do something
}
};

First up is to calculate the total acceleration of the phone. Details on the math and physics behind this is here.

Then I just played around with values that were large enough to occur when the phone hit the ground, but not too small that sudden phone movements would trigger it.

Sound

Sound is played using the expo-av library. Docs are here.

Essentially we load the audio file

const { sound } = await Audio.Sound.createAsync(require('./assets/plate-break.mp3'));

Then save the sound for unloading later.

setSound(sound);

Then playing the sound

await sound.playAsync();

To prevent memory leaks, we then also unload the sound once it's been played

  useEffect(() => {
return sound
? () => {
console.log('Unloading Sound');
sound.unloadAsync();
}
: undefined;
}, [sound]);