Oreo: Broadcast receiver Not working
I faced this issue for a long time. And every one will provide you a link to google developers site, which describes nothing than how they are having limits on background services; with no proper documentation and no sample code showing developers, how to implement it on Oreo or Higher. Even on stack-Overflow you will find only links to the google developers site on limitations.
I hope you or some other developer will find this very helpful.
There are still some exclusions like NEW_OUTGOING_CALL
OR BOOT_COMPLETED
which you can still use in manifest. But its a good practise to implement runtime at application context. I wanted my PHONE_STATE
ready always for getting incoming and outgoing calls; On every reboot too...
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rushi.boottest">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="26" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".CatchNumbers"
android:enabled="true"
android:exported="true" />
<service
android:name=".WatchMan"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
In above manifest.xml i have not placed WRITE_EXTERNAL_STORAGE
and READ_EXTERNAL_STORAGE
. It has automatically inserted by android studio as i implemented it runtime.
Here is my OnBoot Receiver :
package com.example.rushi.boottest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Log.d("BootTest : ", "\nOnBootReceiver - Received a broadcast!");
Toast.makeText(context, "OnBootReceiver Received a broadcast!!", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, WatchMan.class));
}
else
{
context.startService(new Intent(context, WatchMan.class));
}
}
}
Here is WatchMan.java a foreground service that implements receivers runtime
public class WatchMan extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "17";
private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
String PhoneNumber = "UNKNOWN";
Log.d("RECEIVER : ","IS UP AGAIN....");
try
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if(state == null)
{
PhoneNumber = "UNKNOWN";
}
else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("RECEIVER : ","Incoming number : "+PhoneNumber);
}
if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.d("RECEIVER : ","Outgoing number : "+PhoneNumber);
}
if(!PhoneNumber.contentEquals("UNKNOWN"))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, CatchNumbers.class));
}
else
{
context.startService(new Intent(context, CatchNumbers.class));
}
}
}
catch (Exception e)
{
e.printStackTrace();
Log.e("RECEIVER : ", "Exception is : ", e);
}
}
};
public WatchMan() { }
@Override
public void onCreate()
{
super.onCreate();
Log.d("WatchMan : ", "\nOnCreate...");
IntentFilter CallFilter = new IntentFilter();
CallFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
CallFilter.addAction("android.intent.action.PHONE_STATE");
this.registerReceiver(mCallBroadcastReceiver, CallFilter);
Log.d("WatchMan : ", "\nmCallBroadcastReceiver Created....");
mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this, null);
mBuilder.setContentTitle("Insta Promo")
.setContentText("Checking New Numbers")
.setTicker("Checking New Numbers")
.setSmallIcon(R.drawable.ic_launcher_background)
.setPriority(Notification.PRIORITY_LOW)
.setDefaults(Notification.DEFAULT_ALL)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setAutoCancel(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
mNotifyManager.createNotificationChannel(notificationChannel);
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
startForeground(17, mBuilder.build());
}
else
{
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
//startForeground(17, mBuilder.build());
mNotifyManager.notify(17, mBuilder.build());
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("WatchMan : ", "\nmCallBroadcastReceiver Listening....");
//return super.onStartCommand(intent, flags, startId);
return START_NOT_STICKY;
}
@Override
public void onDestroy()
{
this.unregisterReceiver(mCallBroadcastReceiver);
Log.d("WatchMan : ", "\nDestroyed....");
Log.d("WatchMan : ", "\nWill be created again....");
}
@Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
Now in the receiver before calling insert phone numbers into sqlite
database table; so that you can read it from CatchNumbers.java service and perform whatever actions you wants on incoming and outgoing numbers. Hope it helps you or someone else
user1955126
Updated on June 04, 2022Comments
-
user1955126 almost 2 years
I was trying to get notification trigger on my application whenever the user makes a new call. I'm registering receiver in my activity and destroying it in onDestroy() method. Following is the code snippets for registering
registerReceiver(inComingCall = new IncomingCall(),new IntentFilter("android.intent.action.PHONE_STATE"));
The issue I'm facing is I'm not getting any trigger in override onReceive() method for the Broadcast receiver. Kindly let me know whether any new implementations or the separate way I should do for receiving the broadcast especially for Oreo.
Thanks in Advance.
-
Era Singla almost 6 yearsHi @Sandhya, Can you please have a look at my query? stackoverflow.com/questions/51221680/…
-
Krupa Kakkad over 5 yearsPerfect Solution...Thanks :)
-
Feroz Siddiqui over 5 yearsit seems not working now. Its not woking in One plus 5 handset
-
sandhya sasane over 5 years@FerozSiddiqui, One plus X, is a one of NON STANDARD MOBILE PHONE MANUFACTURERS.., there are multiple like VIVO, MI, ......... Its OXYGEN OS AND NOT STOCK ANDROID OS. ( you need to be battery optimisation off to work on it. I have tested it on One Plus 3 and it works.. As post oreo you have to make battery optimisation exemption, ask users to exempt )
-
mdroid almost 4 yearsNot working, when the app is not running. If the app is killed or removed from the recent screen then the app does not receive any broadcast.