Mobile application development is a way faster when you use simulators/emulators. Nowadays, you can test nearly all major features of mobile phone API, without running application on a real device. It’s very helpful and speeds up the whole process. Some time ago Apple released a new version of Xcode with a new, shiny simulator. And thanks to that, we can now test our PUSH notifications without a real device! Even on applications built with Expo. Check out how!
The most important step is to update Xcode to version 11.4+. It contains a new version of a simulator with a vary of new features - including PUSH notifications.
More info about this version you can find in this release note.
If you don’t have an app yet, we’ll prepare simple example now, based on the latest documentation of Expo. There you can find, how to set up project. The most important part for us is to set listeners on PUSH notifications. We can do this in the same way, how we configure listeners for a standalone app. So, in our App.js we have to add something like that (the original code you can find in documentation):
import React from 'react';
import { Text, View, Button, Vibration, Platform } from 'react-native';
import { Notifications } from 'expo';
import * as Permissions from 'expo-permissions';
export default class AppContainer extends React.Component {
state = {
notification: {},
};
componentDidMount() {
this._notificationSubscription = Notifications.addListener(this._handleNotification)
}
registerForPushNotificationsAsync = async () => {
const { status: existingStatus } = await Permissions.getAsync(Permissions.NOTIFICATIONS)
let finalStatus = existingStatus
if (existingStatus !== 'granted') {
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS)
finalStatus = status
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!')
return
}
}
_handleNotification = notification => {
this.setState({ notification })
}
render() {
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'space-around',
}}>
<View style={{ alignItems: 'center', justifyContent: 'center' }}>
<Text>Origin: {this.state.notification.origin}</Text>
<Text>Data: {JSON.stringify(this.state.notification.data)}</Text>
</View>
</View>
)
}
}
As you may see, we change the original code a bit; We don’t need ExpoNotificationToken (we cannot get it on simulators, anyway), and we only set listeners and ask for permissions for notifications.
Such prepared application we can run on our iOS simulator.
The key part is to prepare a specific .apns file. On the Internet, you can find a lot of tutorials, how to run notifications on iOS simulator, but we will focus on a specific case: Expo wrapped applications.
Let’s create notification-test.apns
file and put such content inside:
{
"Simulator Target Bundle": "host.exp.Exponent",
"aps": {
"alert": {
"title": "EXPO iOS Simulator PUSH",
"body": "It works!"
}
},
"experienceId": "@rduraj/example_app",
"body": {
"type": "IOS_PUSH",
"example": {
"exampleField": "text"
}
}
}
Let’s go through the most important parts of it:
Simulator Target Bundle
- Bundle ID of Expo client app on your simulator, because Expo Client is the main recipient and it will broadcast notification to our app.aps.alert.*
- object with notification details, which will be used by the system, to display proper notification bubble, set badge number, etc.body
- this object will be delivered as our notification dataexperienceId
- the most important property; Expo Client, based on this information, runs a specific app and provides notification data to it. In this example, it points to app on my account. experienceId is a mix of @{expo_username}/{app_slug}
, app_slug
you can find in app.json
file inside your project.Important: You have to be logged in both: CLI and Expo client app on your simulator.
As I mentioned, there are a couple of ways to run notifications on a simulator. Personally, I prefer CLI way. On your terminal, you just have to run one command:
$ xcrun simctl push booted ./notification-test.apns
booted
in this command means, that this notification will be delivered to the current running simulator. If you want to choose a specific one, you can list all of the simulators by command:
$ xcrun simctl list
and replace booted
by a particular device ID.
After that, you should see your notification on the simulator and the app should be shown after tapping on this bubble (if you have Expo Client in the background, vide: Caveats).
We have to say this loud: simulator’s notifications are just simulation of real notifications and we have to treat them like that. They are great for styling internal notifications or checking behaviors. But we have to keep in mind, that this method is not sufficient enough to replace tests on real devices;
To get the most from simulating notifications, you have to remember about some rules:
yarn start
and you have to log in to Expo Client, right after the first run of a client on your simulator;That’s all. I hope you will find this method useful, speeds up your work and makes it more comfortable!
Happy testing!