push notifications
device token
app development
mobile notifications
notification services

Get device token for push notification

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

A device token is a unique identifier assigned by a push notification service (APNs for iOS, FCM for Android) to a specific app installation on a specific device. Your app must request this token, send it to your backend server, and your server uses it to target push notifications to that device. Tokens can change, so your app must handle token refresh.

How Push Notification Tokens Work

  1. Your app registers with the OS push notification service
  2. The OS contacts Apple (APNs) or Google (FCM) servers
  3. The service returns a unique device token
  4. Your app sends this token to your backend server
  5. Your server stores the token and uses it to send notifications via APNs/FCM

iOS: Getting the APNs Device Token

Request Permission and Register

swift
1import UserNotifications
2
3class AppDelegate: UIResponder, UIApplicationDelegate {
4
5    func application(_ application: UIApplication,
6                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
7
8        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
9            if granted {
10                DispatchQueue.main.async {
11                    application.registerForRemoteNotifications()
12                }
13            }
14        }
15        return true
16    }
17
18    // Called when registration succeeds
19    func application(_ application: UIApplication,
20                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
21
22        // Convert token to hex string
23        let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
24        print("Device token: \(token)")
25
26        // Send to your server
27        sendTokenToServer(token)
28    }
29
30    // Called when registration fails
31    func application(_ application: UIApplication,
32                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
33        print("Failed to register: \(error.localizedDescription)")
34    }
35}

Token Format

APNs tokens are binary data, typically 32 bytes. Convert to a hex string before sending to your server:

swift
// The token as a hex string looks like:
// "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"

Android: Getting the FCM Token

Using Firebase Cloud Messaging

kotlin
1import com.google.firebase.messaging.FirebaseMessaging
2
3class MainActivity : AppCompatActivity() {
4
5    override fun onCreate(savedInstanceState: Bundle?) {
6        super.onCreate(savedInstanceState)
7
8        FirebaseMessaging.getInstance().token
9            .addOnCompleteListener { task ->
10                if (task.isSuccessful) {
11                    val token = task.result
12                    Log.d("FCM", "Token: $token")
13                    sendTokenToServer(token)
14                } else {
15                    Log.w("FCM", "Failed to get token", task.exception)
16                }
17            }
18    }
19}

Handling Token Refresh

Tokens can change when the app is reinstalled, data is cleared, or the OS rotates tokens. Override onNewToken to catch updates:

kotlin
1class MyFirebaseMessagingService : FirebaseMessagingService() {
2
3    override fun onNewToken(token: String) {
4        super.onNewToken(token)
5        Log.d("FCM", "New token: $token")
6        sendTokenToServer(token)
7    }
8
9    override fun onMessageReceived(message: RemoteMessage) {
10        // Handle incoming notification
11        message.notification?.let {
12            showNotification(it.title, it.body)
13        }
14    }
15}

Register the service in AndroidManifest.xml:

xml
1<service
2    android:name=".MyFirebaseMessagingService"
3    android:exported="false">
4    <intent-filter>
5        <action android:name="com.google.firebase.MESSAGING_EVENT" />
6    </intent-filter>
7</service>

Sending the Token to Your Server

swift
1// iOS
2func sendTokenToServer(_ token: String) {
3    var request = URLRequest(url: URL(string: "https://api.yourapp.com/devices")!)
4    request.httpMethod = "POST"
5    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
6
7    let body: [String: Any] = [
8        "token": token,
9        "platform": "ios",
10        "app_version": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
11    ]
12    request.httpBody = try? JSONSerialization.data(withJSONObject: body)
13
14    URLSession.shared.dataTask(with: request) { _, response, error in
15        if let error = error {
16            print("Failed to send token: \(error)")
17        }
18    }.resume()
19}
kotlin
1// Android (using Retrofit)
2interface DeviceApi {
3    @POST("devices")
4    suspend fun registerDevice(@Body device: DeviceRegistration): Response<Unit>
5}
6
7data class DeviceRegistration(
8    val token: String,
9    val platform: String = "android",
10    val appVersion: String
11)

Server-Side: Storing and Using Tokens

python
1# Python backend example
2from firebase_admin import messaging
3
4def send_push(token, title, body):
5    message = messaging.Message(
6        notification=messaging.Notification(title=title, body=body),
7        token=token,
8    )
9    try:
10        response = messaging.send(message)
11        print(f"Sent: {response}")
12    except messaging.UnregisteredError:
13        # Token is invalid — remove from database
14        delete_token(token)
15    except Exception as e:
16        print(f"Failed: {e}")

Common Pitfalls

  • Tokens change: Device tokens are not permanent. They can change when the app is reinstalled, the device is restored from backup, or the OS rotates them. Always handle onNewToken (Android) and didRegisterForRemoteNotificationsWithDeviceToken (iOS) to update your server.
  • Simulator tokens: iOS simulators do not receive real APNs tokens. You must test on a physical device. Android emulators with Google Play Services can receive FCM tokens.
  • Stale tokens: If you send to an expired or unregistered token, APNs returns a 410 response and FCM returns NOT_REGISTERED. Remove these tokens from your database to avoid wasted requests.
  • Security: Always transmit tokens over HTTPS. Tokens themselves are not secret (they cannot be used to read notifications), but they can be used to send unwanted notifications if your server endpoint is not authenticated.
  • Permission denied: On iOS, if the user denies notification permission, registerForRemoteNotifications is never called and you never receive a token. Check authorization status before attempting to register.

Summary

  • Request notification permission, then register for remote notifications to receive a device token
  • On iOS, implement didRegisterForRemoteNotificationsWithDeviceToken to capture the APNs token
  • On Android, use FirebaseMessaging.getInstance().token and override onNewToken for FCM
  • Send the token to your backend over HTTPS and update it whenever it changes
  • Handle invalid/expired tokens by removing them from your database when the push service reports them as unregistered

Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions