How to deal with the FCM notification on custom OS phones such as OPPO, VIVO, MIUI?

I implemented FCM push notification in Android App.
I got all notification JSON in the data payload. I “not added” the’notification’ tag on the api. Therefore, in all states (foreground/background/killed), I only get notifications in the data payload.

It is suitable for non-customized OS phones such as Moto, Google, etc., The app is Foreground/Background/Killed in all states. But the problem is that when I test on a phone with a custom operating system such as Oppo, Vivo or MIUI, the notification is only when the app is in the foreground or background (the app is in the memory When it arrives, the application is “killed” when it does not arrive/appears (not in memory).

What should I do?

Anyway, thank you for your time.

public class MyFirebaseMessagingService extends FirebaseMessagingService{
private static final String TAG = "MyFirebaseMsgService";< br />
/**
* Called when message is received.
*
* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notifica tion is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification< br />
// [END_EXCLUDE]

// TODO(developer): Handle FCM messages here.

Log.e(TAG, "From: " + remoteMessage.getFrom());

// Check if message contains a data payload.
if (remoteMessage.getData().size()> 0)
{< br /> Log.d(TAG, "Message data payload: "+ remoteMessage.getData());

if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds< br /> handleNow();
}

if (remoteMessage.getNotification()!=null)
sendNotification(remoteMessage.getNotification().getBody());
else
sendNotification("Body ");

}

// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null)
{
Log.d(TAG, "Message Notification Body: "+ remoteMessage.getNotification().getBody());
if (remoteMessage.getNotification()!=null)
sendNotification(remoteMessage .getNotification().getBody());
else
sendNotification("Body");

}

// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
// [END receive_message]

/**
* Schedule a job using FirebaseJobDispatcher.
*/
private void scheduleJob() {
// [START dispatch_job]
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTag("my-job-tag")
.build();
dispatcher.schedule(myJob);
// [END dispatch_job]
}

/**
* Handle time allotted to BroadcastReceivers.
* /
private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}

/**
* Create and show a simple notification containing the received FCM message.
*
* @param messageBody FCM message body received.
*/
private void sendNotification(String messageBody)< br /> {
Intent intent = new Intent(this , MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT) ;

String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("FCM Message")
.setContentText(messageBody)
.setAutoCancel( true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
if (notificationManager != null) {
notificationManager.createNotificationChannel( channel);
}
}

if (notificationManager != null) {
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build( ));
}
}

}

My AndroidManifest.xml file is as follows:


android:name=".Firebase.FirebaseId">




android:name="Firebase. MyFirebaseMessagingService"
android:stopWithTask="false">








android:name="com.google.firebase.messaging .default_notification_icon"
android:resource="@drawable/ic_launcher_background" />

android:name="com.google.firebase.m essaging.default_notification_color"
android:resource="@color/colorAccent" />


android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
I found a solution to this problem. Write a custom service for your application, which is The background runs continuously and writes a broadcast receiver to restart the service after the service is terminated. This is fine for me. I tested this on Vivo, Oppo, Redmi phones. This is working!

My service code is as follows-

public class MyService extends Service
{

private static final String TAG = "MyService";


@Override
public void onStart(Intent intent, int startId)
{
// TODO Auto- generated method stub
super.onStart(intent, startId);
}

@Override
public boolean onUnbind(Intent intent) {
return super. onUnbind(intent);
}


@Override
public void onCreate()
{
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
//call to onTaskRemoved
onTaskRemoved( intent);
//return super.onStartCommand(intent, flags, startId);
Toast.makeText(this, "Service Started!", Toast.LENGTH_SHORT).show();

return START_NOT_STICKY;
}

@Nullable
@Override
public IBinder onBind(Intent intent)
{
return null ;
}

@Override
public void onDestroy()
{
Toast.makeText(this, "Service Destroyed!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent("com.myapp.startservice");
//Intent intent = new Intent("android.intent.action.BOOT_COMPLETED");
intent.putExtra( "yourvalue", "torestore");
sendBroadcast(intent);
super.onDestroy();

}


< br />@Override public void onTaskRemoved(Intent rootIntent)
{
Log.e("onTaskRemoved", "Called!");

//thread = new Thread( this);
//startThread();

/*Intent alarm = new Intent(this.getApplicationContext(), MyBroadCastReceiver.class);
boolean alarmRunning = (PendingIntent. getBroadcast(this.getApplicationContext(), 0, alarm, PendingIntent.FLAG_NO_CREATE) != null);
//if(!alarmRunning)
{
PendingIntent pendingIntent = PendingIntent.getBroadcast(this. getApplicationContext(), 0, alarm, 0);< br /> AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 10000, pendingIntent) ;
}
}*/

//send broadcast to your BroadcastReciever
Intent intent = new Intent("com.myapp.startservice"); //unique String to uniquely identify your broadcastreceiver
//Intent intent = new Intent("android.intent.action.BOOT_COMPLETED");
intent.putExtra("yourvalue", "torestore");
sendBroadcast(intent);

//intent to restart your service.
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage( getPackageName());

PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLA G_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
if (alarmService != null) {
alarmService.set(
AlarmManager. ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
}

super.onTaskRemoved(rootIntent);

} }

My BroadcastReceiver is as follows –

public class MyBroadCastReceiver extends BroadcastReceiver
{

@Override
public void onReceive(Context context, Intent intent)
{
Log.e("MyBroadCastReceiver", "onReceive");

//if ("android.intent. action.BOOT_COMPLETED".equals(intent.getAction()))
{
Intent service = new Intent(context, MyService.class);
context.startService(service);
Log.e("BootCompleteReceiver", "__________BootCompleteReceiver _________");

}
}}

My AndroidManifest.xml file is as follows –


android:name=".Service.MyService"
android:exported="false"
android:stopWithTask="false" />

< br />
android:name=".Service.MyBroadCastReceiver"
android:enabled="true"
android: exported="false">









Start the service with my MainActivity.java file code—

public class MainActivity extends AppCompatActivity
{

B utton btnStopService;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_main);

btnStopService = findViewById(R.id.btnStopService);

//get FirebaseToken
getToken();

//start Service
startService();



btnStopService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
}
});

}


private void getToken()
{
FirebaseId firebaseId=new FirebaseId();
String token_firebase=firebaseId.getFireBaseToken ();
}


private void startService()
{

Intent myIntent = new Intent(this, MyService.class) ;
PendingInt ent pendingIntent = PendingIntent.getService(this, 0, myIntent, 0);
Log.e("TAG", "++++++++++222222++++++++") ;
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
// calendar.setTimeInMillis(System.currentTimeMillis());
//calendar.add(Calendar.SECOND, 10);
if (alarmManager != null) {
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}

Toast.makeText(this, "Start Alarm", Toast.LENGTH_LONG).show();

}

private void s( )
{
Intent intent = new Intent(this, MyService.class);
startService(intent);
}}

I implemented FCM push notification in Android App.
I got all notification JSON in the data payload. I “not added” the’notification’ tag on the api. Therefore, in all states (foreground/ In the background/killed), I only get notifications in the data payload.

It is suitable for non-customized OS phones, such as Moto, Google, etc., the application is Foreground in all states /Background/Killed. But the problem is that when I test on a phone with a custom operating system such as Oppo, Vivo, or MIUI, the notification is only when the app is in the foreground or When it arrives in the background (the application is in memory), the application is “killed” when it does not arrive/appears (not in memory).

What should I do?

Anyway, thank you for your time.

public class MyFirebaseMessagingService extends FirebaseMessagingService{
private static final String TAG = "MyFirebaseMsgService";< br />
/**
* Called when message is received.
*
* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notificatio n is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification< br />
// [END_EXCLUDE]

// TODO(developer): Handle FCM messages here.

Log.e(TAG, "From: " + remoteMessage.getFrom());

// Check if message contains a data payload.
if (remoteMessage.getData().size()> 0)
{< br /> Log.d(TAG, "Message data payload: "+ remoteMessage.getData());

if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds< br /> handleNow();
}

if (remoteMessage.getNotification()!=null)
sendNotification(remoteMessage.getNotification().getBody());
else
sendNotification("Body ");

}

// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null)
{
Log.d(TAG, "Message Notification Body: "+ remoteMessage.getNotification().getBody());
if (remoteMessage.getNotification()!=null)
sendNotification(remoteMessage .getNotification().getBody());
else
sendNotification("Body");

}

// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
// [END receive_message]

/**
* Schedule a job using FirebaseJobDispatcher.
*/
private void scheduleJob() {
// [START dispatch_job]
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTag("my-job-tag")
.build();
dispatcher.schedule(myJob);
// [END dispatch_job]
}

/**
* Handle time allotted to BroadcastReceivers.
* /
private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}

/**
* Create and show a simple notification containing the received FCM message.
*
* @param messageBody FCM message body received.
*/
private void sendNotification(String messageBody)< br /> {
Intent intent = new Intent(this, M ainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);

String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("FCM Message")
.setContentText(messageBody)
.setAutoCancel(true )
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
if (notificationManager != null) {
notificationManager.createNotificationChannel( channel);
}
}

if (notificationManager != null) {
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build( ));
}
}

}

My AndroidManifest.xml file is as follows:


android:name=".Firebase.FirebaseId">




android:name="Firebase. MyFirebaseMessagingService"
android:stopWithTask="false">








android:name="com.google.firebase.messaging .default_notification_icon"
android:resource="@drawable/ic_launcher_background" />

android:name="com.google.firebase.messagi ng.default_notification_color"
android:resource="@color/colorAccent" />


android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />

I found a solution to this problem. Write a custom service for your application, which runs continuously in the background and writes to a broadcast receiver, In order to restart the service after the service is terminated. This works fine for me. I tested this on Vivo, Oppo, Redmi phones. This is working!

My service code is as follows-

public class MyService extends Service
{

private static final String TAG = "MyService";


@Override
public void onStart(Intent intent, int startId)
{
// TODO Auto- generated method stub
super.onStart(intent, startId);
}

@Override
public boolean onUnbind(Intent intent) {
return super. onUnbind(intent);
}


@Override
public void onCreate()
{
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
//call to onTaskRemoved
onTaskRemoved( intent);
//return super.onStartCommand(intent, flags, startId);
Toast.makeText(this, "Service Started!", Toast.LENGTH_SHORT).show();

return START_NOT_STICKY;
}

@Nullable
@Override
public IBinder onBind(Intent intent)
{
return null ;
}
@Override
public void onDestroy()
{
Toast.makeText(this, "Service Destroyed!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent("com.myapp.startservice");
//Intent intent = new Intent("android.intent.action.BOOT_COMPLETED");
intent.putExtra("yourvalue ", "torestore");
sendBroadcast(intent);
super.onDestroy();

}



@Override public void onTaskRemoved(Intent rootIntent)
{
Log.e("onTaskRemoved", "Called!");

//thread = new Thread(this) ;
//startThread();

/*Intent alarm = new Intent(this.getApplicationContext(), MyBroadCastReceiver.class);
boolean alarmRunning = (PendingIntent.getBroadcast( this.getApplicationContext(), 0, alarm, PendingIntent.FLAG_NO_CREATE) != null);
//if(!alarmRunning)
{
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext( ), 0, alarm, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 10000, pendingIntent);
}
}*/

//send broadcast to your BroadcastReciever
Intent intent = new Intent("com.myapp.startservice"); //unique String to uniquely identify your broadcastreceiver
//Intent intent = new Intent("android.intent.action.BOOT_COMPLETED");
intent.putExtra("yourvalue", "torestore");
sendBroadcast (intent);

//intent to restart your service.
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName ());

PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_O NE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
if (alarmService != null) {
alarmService.set(
AlarmManager. ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
}

super.onTaskRemoved(rootIntent);

} }

My BroadcastReceiver is as follows –

public class MyBroadCastReceiver extends BroadcastReceiver
{

@Override
public void onReceive(Context context, Intent intent)
{
Log.e("MyBroadCastReceiver", "onReceive");

//if ("android.intent. action.BOOT_COMPLETED".equals(intent.getAction()))
{
Intent service = new Intent(context, MyService.class);
context.startService(service);
Log.e("BootCompleteReceiver", "__________BootCompleteReceiver _________");

}
}}

My AndroidManifest.xml file is as follows –


< service
android:name=".Service.MyService"
android:exported="false"
android:stopWithTask="false" />



android:name=".Service.MyBroadCastReceiver"
android:enabled="true"
android:exported= "false">





< br />


Start the service with my MainActivity.java file code—

public class MainActivity extends AppCompatActivity
{

Button btnSto pService;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main );

btnStopService = findViewById(R.id.btnStopService);

//get FirebaseToken
getToken();

/ /start Service
startService();



btnStopService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
}
});

}


private void getToken()
{
FirebaseId firebaseId=new FirebaseId();
String token_firebase=firebaseId.getFireBaseToken( );
}


private void startService()
{

Intent myIntent = new Intent(this, MyService.class);
PendingIntent pendingI ntent = PendingIntent.getService(this, 0, myIntent, 0);
Log.e("TAG", "++++++++++222222++++++++");
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
// calendar.setTimeInMillis(System.currentTimeMillis());
/ /calendar.add(Calendar.SECOND, 10);
if (alarmManager != null) {
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}

Toast.makeText(this, "Start Alarm", Toast.LENGTH_LONG).show();

}

private void s()
{
Intent intent = new Intent(this, MyService.class);
startService(intent);
}}

Leave a Comment

Your email address will not be published.