Android FAQ

What does Android push token and HWID look like?

Android device push tokens can differ in length (usually below 255 characters), and usually start with APA… Push token example:

APA91bFoi3lMMre9G3XzR1LrF4ZT82_15MsMdEICogXSLB8-MrdkRuRQFwNI5u8Dh0cI90ABD3BOKnxkEla8cGdisbDHl5cVIkZah5QUhSAxzx4Roa7b4xy9tvx9iNSYw-eXBYYd8k1XKf8Q_Qq1X9-x-U-Y79vdPq

Using raw device tokens for targeting specific devices is not the most reliable way because GCM push tokens tend to change from time to time, and it’s hard to tell how often it occurs. Therefore, we strongly recommend using Tags to send pushes to specific devices. HWID example:

a9f282012f5dce9e

How can I obtain my Android device push token?

You can obtain your Android device push token in the console log. Use the logcat tool in Android Studio.

Open monitor.bat in %USERPROFILE%\AppData\Local\Android\sdk\tools\monitor.bat, connect your device to PC and allow USB debugging in Android settings. Run your application on the device. Locate /registerDevice, find the push token for your device to use in Test Devices later on.

What permissions are necessary and what are optional?

When installed on an Android device, the application will ask for the following permissions in connection with Pushwoosh SDK:

<!-- FCM connects to Firebase Services. -->
 <uses-permission android:name="android.permission.INTERNET"/>
  
<!-- Keeps the processor from sleeping when a message is received. -->
 <uses-permission android:name="android.permission.WAKE_LOCK"/>
 
 <!-- This permission is used to determine whether the device can access the network. -->
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 
<!-- This app has permission to register and receive data message. -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

Our SDK doesn’t ask for permission to access images, device contacts, etc.

How accurate is the total number of Android subscribers?

Pushwoosh clears unsubscribed Android devices from the database upon receiving the “NotRegistered” response from FCM, which can be returned after the second attempt to reach a specific device. It means that you have to send 2 pushes to an unsubscribed device to have it removed from our database.
Here’s the most common scenario described in the FCM documentation:

  1. Your subscriber uninstalls the app.
  2. Pushwoosh sends a message to FCM server.
  3. The FCM server sends the message to your user’s device.
  4. The FCM client on the device receives the message and detects that your application has been uninstalled; the detection details depend on the platform on which the app is running.
  5. The FCM client on the device informs the FCM server that the app was uninstalled.
  6. The FCM server marks the registration ID for deletion.
  7. Pushwoosh sends another message to FCM.
  8. The FCM returns a NotRegistered message.
  9. Pushwoosh removes the push token from your userbase.

It might take a while for registration ID to be completely removed from FCM. Thus it is possible a message sent in step 7 above gets a valid message ID as response, even though the message will not be delivered to the client app.

Can I use HTML tags in pushes sent to Android?

Yes, in Android you may use the following HTML tags in order to modify the appearance of a push:

<span style="color: green;"><b><i><span style="text-decoration: underline;">Hello world!
Hello hi hey</span></i></b></span>

Place these HTML tags in the Message input field, and use them in the API request as well. Note that some Android devices may fail to process these HTML tags properly, but most of the devices we have used for tests displayed formatting properly.

How to set a notification icon in Android Lollipop (and later versions)?

In Android Lollipop icons were changed to be white only. Therefore, if you select targetSdkVersion >= 21 in your AndroidManifest.xml file, Android will only use alpha-channel of the icon.
See more on the behavior in Android documentation.

The system ignores all non-alpha channels in action icons and in the main notification icon. Assume these icons will be alpha-only. The system draws notification icons in white and action icons in dark gray. This is beyond Pushwoosh SDK control.

1. Create the notification icon according to the Android guidelines. As per documentation, the system will ignore all the colors.
1.1. Name the icon as pw_notification.png and put it in res/drawable folder. Pushwoosh SDK will use this icon as default for notifications.
1.2. Alternatively, you can use Remote API and set the "android_icon" parameter value to the icon image (without file extension).

Using Pushwoosh SDK with other FCM services

You can use Pushwoosh alongside with other SDKs that use FCM for push messaging. To do that you should create a router service to distribute events between the services:

class FirebaseMessagingRouterService : FirebaseMessagingService() {

  override fun onMessageReceived(remoteMessage: RemoteMessage) {
        if (PushwooshFcmHelper.isPushwooshMessage(remoteMessage)) {
           //this is a Pushwoosh push, SDK will handle it automatically
            PushwooshFcmHelper.onMessageReceived(remoteMessage)
        } else {
            //this is not a Pushwoosh push, you should handle it by yourself
            dispatchNonPushwooshMessage(remoteMessage);
        }
    }
  
    private fun dispatchNonPushwooshMessage(remoteMessage: RemoteMessage) {
       // Implement your push handling logics here    
   }
}
public class FirebaseMessagingRouterService extends FirebaseMessagingService {

  	@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        if (PushwooshFcmHelper.isPushwooshMessage(remoteMessage)) {
						 //this is a Pushwoosh push, SDK will handle it automatically
            PushwooshFcmHelper.onMessageReceived(remoteMessage);
        } else {
            //this is not a Pushwoosh push, you should handle it by yourself
            dispatchNonPushwooshMessage(remoteMessage);
        }
    }
  
    private void dispatchNonPushwooshMessage(RemoteMessage remoteMessage) {
        // Implement your push handling logics here    
    }
}

Take care of listening to push token changes:

class FirebaseInstanceIdRouterService : FirebaseInstanceIdService() {

     override fun onTokenRefresh() {
        // Get updated InstanceID token.
        val refreshedToken = FirebaseInstanceId.getInstance().token

        // Send a new token to Pushwoosh
        PushwooshFcmHelper.onTokenRefresh(refreshedToken)
        sendTokenToAnotherService(token);
    }

    private fun sendTokenToAnotherService(token: String) {
        // Implement your token handling logics here
    }
}
public class FirebaseInstanceIdRouterService extends FirebaseInstanceIdService {

    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();

				// Send a new token to Pushwoosh
        PushwooshFcmHelper.onTokenRefresh(refreshedToken);
        sendTokenToAnotherService(token);
    }

    private void sendTokenToAnotherService(String token) {
        // Implement your token handling logics here
    }
}

Register the routers in your AndroidManifest.xml:

<service
    android:name=".FirebaseInstanceIdRouterService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
       
<service
    android:name=".FirebaseMessagingRouterService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

Using Pushwoosh with LeakCanary or AppMetrica libraries

When you integrate analytics tools such as LeakCanary, AppMetrica or others, these libraries start a new process, creating new instance of the app. Since you can't listen for the push notifications in another process, this results in java.lang.NullPointerException being thrown.

If you call registerForPushNotifications inside Application.onCreate(), you should check if you are in the application's main process. Use the following code to perform this check:

List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE)).getRunningAppProcesses();
if (runningAppProcesses != null && runningAppProcesses.size() != 0) {
    for (ActivityManager.RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses) {
        boolean isCurrentProcess = runningAppProcessInfo.pid == android.os.Process.myPid();
        boolean isMainProcessName = getPackageName().equals(runningAppProcessInfo.processName);
        if (isCurrentProcess && isMainProcessName) {

            Pushwoosh.getInstance().registerForPushNotifications(...);
            break;
        }
    }
}

Android FAQ