This is yet another question about why a BroadcastReceiver doesn't see the messages being sent to it. I've looked at a dozen examples and other questions their solutions seem the same as mine but mine doesn't work.
My receiver is in a service. Here's the manifest fragment:
<service android:name="com.madurasoftware.vmnotifications.services.BLEService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
The service registers the receiver like this:
private val messageReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive() called")
val message = intent.getStringExtra(BluetoothService.MESSAGE)
NotificationQueue.add(message)
}
}
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate() called")
val filter = IntentFilter()
filter.addAction(BluetoothService.MESSAGE_ACTION)
baseContext.registerReceiver(this.messageReceiver, filter )
}
override fun onDestroy() {
baseContext.unregisterReceiver(this.messageReceiver)
}
Because I am dynamically registering the receiver I don't add anything about it to the manifest.
I send from a button in my MainActivity like this:
Intent().also { intent ->
intent.setAction(BluetoothService.MESSAGE_ACTION)
intent.putExtra(BluetoothService.MESSAGE, "xyz")
sendBroadcast(intent)
}
Log.d(TAG, "sendBroadcast() called")
When I press the button I see that the logged sendBroadcast() message shows up, but the onReceive() log message does not. So it isn't being delivered.
Can anyone see why?
I'm using API 29 and this is my full manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.madurasoftware.vmnotifications">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<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"
android:fullBackupContent="#xml/my_backup_rules">
<activity android:name=".ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="com.madurasoftware.vmnotifications.services.NotificationService"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<service android:name="com.madurasoftware.vmnotifications.services.BLEService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
<service android:name="com.madurasoftware.vmnotifications.services.BluetoothService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
</application>
</manifest>
Thanks for any help
Related
I'm working on an android application and i need alarm manager to fire events at certain times , the code works fine and the notification fires in time but only in one scenario is not working when the screen is off , the device is not waking up and wait for notification to fire up , actually this works in emulators ( i guess because there is no such power saving mode like in some physical devices ) , I've looked up most topics and could not find any solution , any help would be appreciated Thank you .
Firing Alarm Manager
fun fireAlarmManager(context: Context , time : MutableList<Long>){
val intent = Intent(context, AlarmReceiver::class.java)
for (i in 0 until time.size){
if(time[i] > deviceTimeInMillis()){
list.add(time[i])
val pendingIntent = PendingIntent.getBroadcast(context,time[i].toInt(),intent,PendingIntent.FLAG_IMMUTABLE)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time[i],pendingIntent)
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP,time[i],pendingIntent)
}
}
}
setDataFromSharedPreferences(list)
}
Broadcast receiver
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context : Context?, intent : Intent?) {
wakeUp(context)
val serviceIntent = Intent(context,OnClearFromRecentServices::class.java)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
context!!.startForegroundService(serviceIntent)
} else {
context!!.startService(serviceIntent)
}
}
private fun wakeUp(context: Context?) {
val pm = context!!.getSystemService(Context.POWER_SERVICE) as PowerManager
val wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.FULL_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, "app::tag")
wakeLock.acquire(60000)
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val keyguardLock = keyguardManager.newKeyguardLock("TAG")
keyguardLock.disableKeyguard()
}
}
Alarm Service
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
fireNotification(this)
return START_STICKY
}
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.kotlin.quranapp">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".koin.BaseApplication"
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:largeHeap="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.QuranApp"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="false"
android:launchMode="singleInstance"
android:screenOrientation="portrait" />
<activity
android:name=".views.SplashActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".alarm.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver
android:name=".alarm.PlayerReceiver"
android:exported="false" />
<service android:name=".alarm.services.OnClearFromRecentServices" />
</application>
</manifest>
I'm trying to start a service in my app when the phone on which the app is running, boots. I've added a broadcastreceiver, added an intent-filter in the manifest, created a service and added that to the manifest as well. But whenever I boot my phone, after a while it displays that my app has crashed.
An important thing to note is that the service works if it started from MainActivity.
I've seen more questions about this on Stackoverflow, but none of these solve my problem because most of them were of people who forgot to add the receiver to the manifest or something else.
But I don't know how to read logcat-output as well, from when a phone starts, so I can't determine what's crashing the app.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="nl.arnovanliere.nuntia">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-feature android:name="android.hardware.location.gps" />
<application
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:resizeableActivity="false"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsPictureInPicture="false"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<receiver
android:name=".receivers.BroadcastReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service
android:name=".services.CheckMessagesService"
android:enabled="true"
android:exported="true"
android:permission="false" />
<activity
android:label="#string/app_name"
android:name=".MainActivity"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyBhlLDqLSihI41pIs-ELuomRWUv6513CeE" />
</application>
</manifest>
BroadcastReceiver.kt
class BroadcastReceiver : BroadcastReceiver() {
#SuppressLint("UnsafeProtectedBroadcastReceiver")
override fun onReceive(context: Context?, intent: Intent?) {
context?.startService(Intent(context, CheckMessagesService::class.java))
Log.d(LOG_TAG, "onReceive BroadcastReceiver called")
}
}
CheckMessagesService
class CheckMessagesService : Service() {
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onCreate() {
Log.d(LOG_TAG, "onCreate of service called")
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(LOG_TAG, "onStartCommand of service called")
val runnable = Runnable {
checkMessages()
// Only need to check for messages every minute
Thread.sleep(60000)
}
// New thread for checking messages, otherwise the UI-thread would be blocked
val thread = Thread(runnable)
thread.start()
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
Log.d(LOG_TAG, "onDestroy of service called")
super.onDestroy()
}
checkMessages() is just a function that calls an API and deserializes it to check if a notification has to be send.
I hope one of you can help me.
For any future viewers: The problem was that I had to use startForegroundService() instead of startService() because I was running it on Android Oreo.
Thanks #Pawel
In my application I am trying to receive broadcast Media_Scanner_Finished. But the receiver is not getting called.
Here is my code-
'<?xml version="1.0" encoding="utf-8"?>'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="objectdistance.ankeshkjaisansaria.ram.sita.MyApp">
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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="objectdistance.ankeshkjaisansaria.ram.sita.myApp.broadcastreceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_SCANNER_FINISHED"/>
<action android:name="android.intent.action.MEDIA_SCANNER_STARTED"/>
<action android:name="android.intent.action.MEDIA_SCANNER_STARTED"/>
<data android:scheme="file" />
</intent-filter>
</receiver>
</application>
</manifest>
In my Broadcast receiver class:-
public class broadcastreceiver extends BroadcastReceiver {
BroadcastReceiver mMediaScannerReceiver;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.i("INFO", "Enter BroadcastReceiver");
}
}
I think the issue is relating to permission required in manifest file to get access to Media_Scanner broadcast.
One more thing I would like to clear is that :- Does Media_Scanner_Started gets called when content provider Media Image database gets updated ?
Add the receiver in code rather than in the manifest:
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
filter.addDataScheme("file");
scannerStartedReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
}
}
I have two broadcast receiver. one for sms and one for call.
I confront this error. i see this page:
BroadcastReceiver trying to return result during a non-ordered broadcast - SMS Receiver
but I don't how ti use that suggestion.
Context.sendOrderedBroadcast.
and if this is helpful or not. I have other receiver in this package for sms this receiver work fine. but this one doesn't work.
public class PhoneCallReceiver extends BroadcastReceiver {
Context context = null;
SharedPreferences preferences = null ;
Boolean blacklist;
Boolean contact;
Boolean all;
public void onReceive(Context context, Intent intent) {
preferences = context.getSharedPreferences("modes",Context.MODE_PRIVATE);
if (intent.getAction().equals("android.intent.action.PHONE_STATE")) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
String phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (preferences.getBoolean("all", true)){
Log.i("all", ": " + phoneNumber);
abortBroadcast();
Log.i("block: ", phoneNumber);
}
else if (preferences.getBoolean("blacklist", true)){
boolean str=Search.search(phoneNumber);
if (phoneNumber != null && str ==true) {
abortBroadcast();}}
else if (preferences.getBoolean("c", true)&&getDetails(phoneNumber)){
abortBroadcast();}
else if (preferences.getBoolean("g", true)){
boolean str=SearchInWhiteList.search(phoneNumber);
if (phoneNumber != null && str ==true) {
abortBroadcast();}}
else if (preferences.getBoolean("b", true)){
abortBroadcast();}
else {}
}
}
}
manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="blocker.activity"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".FirstPage"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".SmsFilter" android:enabled="true">
<intent-filter android:priority="999">
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="bloker.activity.android.action.broadcast"/>
<action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
<receiver android:name=".PhoneCallReceiver" android:enabled="true">
<intent-filter android:priority="999">
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="bloker.activity.android.action.broadcast"/>
</intent-filter>
</receiver>
<activity
android:name=".Search"
android:label="#string/app_name" >
</activity>
<activity
android:name=".BlockActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name=".SmsFilter"
android:label="#string/app_name" >
</activity>
<activity
android:name=".CustomAdapter"
android:label="#string/app_name" >
</activity>
<activity
android:name=".Setting"
android:label="#string/app_name" >
</activity>
<activity
android:name=".GetAllContact"
android:label="#string/app_name" >
</activity>
<activity
android:name=".WhiteList"
android:label="#string/app_name" >
</activity>
</application>
</manifest>
edit:
broadcastreceiver fro incoming call to android phone is non-ordering. so that cant be aborted using above code. my question is that how can we handle this kind of broadcast?
I know that using this code can block call.
Can I hang up a call programmatically in android?
but my question is that how to use above code to abort call?
You cannot abort the broadcast or programmatically hang up a call. Telephony control can only be done by the Phone app. The broadcasts you are registered to receive are informative only: they tell you about state changes but they are not something which is triggering state changes or driving the telephony state machine.
You can intercept/modify outgoing calls using the ordered broadcast with action of ACTION_NEW_OUTGOING_CALL but there's no public way to intercept an incoming call.
When I create class that extends BrodcastReceiver and register it.
Error Unable to destroy activity, Receiver not registered: null onDestroy() function in MainActivity When call unregisterReceiver.
onCreate():
ConnectionChangeReceiver connectionChangeReceiver = new ConnectionChangeReceiver();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(connectionChangeReceiver, filter);
onDestroy():
#Override
protected void onDestroy() {
Log.v("YourActivity", "onDestroy");
unregisterReceiver(connectionChangeReceiver);
super.onDestroy();
}
ConnectionChangeReceiver Class:
public class ConnectionChangeReceiver extends BroadcastReceiver
{
#Override
public void onReceive( Context context, Intent intent )
{
Toast.makeText(context, "CONN", Toast.LENGTH_SHORT).show();
}
}
manifest: UPDATE: After adding <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mamrezo.mapapp" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.mamrezo.mapapp.MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".ConnectionChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
</manifest>
I always register the receiver in the onStart and unregister it in the onStop. I knew this thanks to this answer : https://stackoverflow.com/a/24391706/1203797
If its still not working in your case, simply wrapunregisterReceiver(connectionChangeReceiver); a try-catch block would be the answer, as stated in the link i posted above.
Or you can register it in the manifest, example :
<receiver android:name=".ConnectionChangeReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>