Reputation: 6426
I try to receive PHONE_STATE intents with next BroadcastReceiver
<receiver android:name=".CallReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
But after rebooting my Nexus 5X and making the call to this device, ringing events can be received after the call has been already finished a minute ago. How can I fix it? Any ideas?
Upvotes: 8
Views: 3920
Reputation: 3673
According to CommonsWare in this answer-
There are many, many apps that want to get control at boot time. How quickly yours will get its turn will depend on many variables, such as the number of installed apps, the CPU speed of the device, the amount of system RAM on the device, etc.
Also, starting an activity from a BroadcastReceiver at boot time is fairly evil. If you want to be the first thing the user sees after a reboot, write a home screen implementation.
All you can do is give priority like this -
<action android:name="android.intent.action.BOOT_COMPLETED" android:priority="999"/>
Upvotes: 2
Reputation: 3979
You can use foreground service and register your receiver in your foreground service instead of manifest. Using a foreground service may reduce delay as foreground service is more important than background service and registered receiver in a foreground service may be more important to OS than registered receiver in manifest as always your program is running and in foreground before phone state is changed.
Also i do not think ACTION_PHONE_STATE_CHANGED
is an Ordered Broadcast as it could not be aborted by receiver thus using Priority which other answers suggest has no effect on it (priority is only for ordered broadcasts).
remove phone state receiver from manifest but keep your BOOT_COMPLETED receiver in manifest and start following service at boot complete
register receiver in onCreate of a Service:
@Override
public void onCreate() {
super.onCreate();
phoneStateReceiver = new PhoneStateReceiver();
registerReceiver(phoneStateReceiver, new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED));
}
unregister in onDestroy:
@Override
public void onDestroy() {
unregisterReceiver(phoneStateReceiver);
super.onDestroy();
}
add a static method to your service to start service:
// start service even if your app is in stopped condition in android 8+
static void requestStart(@NonNull final Context context, @NonNull final String action){
final Context appContext = context.getApplicationContext();
Intent intent = new Intent(appContext, AppService.class);
intent.setAction(action);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// this is required to start the service if there is
// no foreground process in your app and your app is
// stopped in android 8 or above
appContext.startForegroundService(intent);
} else {
appContext.startService(intent);
}
}
start foreground in your onStartCommand
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(ACTION_START.equals(intent.getAction()))
startForeground(ID, notification);
else if(ACTION_STOP.equals(intent.getAction()))
stopForeground(true);
return START_STICKY;
}
Upvotes: 1
Reputation: 843
I'm thinking when you create Intent for send Broadcast, you miss set flag for intent. You need set tag FLAG_RECEIVER_FOREGROUND for your intent.
I don't see source code create Intent to sent Broadcast in this topic so I suggest a sample:
Intent intent = new Intent();
intent.setAction(...);
intent.setFlags(FLAG_RECEIVER_FOREGROUND);
...
You can see more at: https://developer.android.com/reference/android/content/Intent.html#FLAG_RECEIVER_FOREGROUND
EDIT:
I has just changed file AndroidManifest, you can try it:
<receiver android:name=".CallReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Upvotes: 1
Reputation: 26994
ACTION_PHONE_STATE_CHANGED
doesn't have the FLAG_RECEIVER_FOREGROUND
flag, hence it runs in the background queue.
Hypothesis: On startup, there are often many applications which are listening to BOOT_COMPLETED
(yes, that's a bad practice, but some people still do it, you should blame them) and as a result the background queue is quite busy. I'm not surprise that another background broadcast added in a busy queue takes a minute to be handled
You can confirm my hypothesis by looking in logcat for
ActivityManager: processNextBroadcast
As an alternative, you could register a listener on the phone log content provider.
Upvotes: 0
Reputation: 1
The value must be greater than -1000 and less than 1000. please,go through below link
http://developer.android.com/guide/topics/manifest/intent-filter-element.html
Upvotes: 0
Reputation: 221
this because there any other Receiver listen to this broadcast, you can try to improve you Recevier' priority just like that
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
Upvotes: 2