Disabling BroadcastReceiver for Oreo? - android

I have a receiver registered in my app's manifest file with action BOOT_COMPLETED.
There is a third-party library in my app and when it receives BOOT_COMPLETED action, it starts a service. Since there is background execution limits in Android Oreo, it crashes.
Now, I want to disable this receiver for only Android O devices. Is there a way to do this? Maybe just like #TargetApi but in Android Manifest?
I forgot to write that I cannot change library class, it's an external jar file.

Since Library's code is not in your control, any approach won't work. You should ask the library provider to comply with latest OS.
You can try following work around:
Register BOOT_COMPLETED in your app with high priority as follows:
<action android:name="android.intent.action.BOOT_COMPLETED" android:priority="999"/>
Start a Foreground Service immediately
This might allow your library to start background service.
Alternatively, If you have access to the BootReceiver class of the library, you can disable it as follows:
PackageManager pm = getPackageManager();
ComponentName compName =
new ComponentName(getApplicationContext(),
<library_broadcastreceiver>.class);
pm.setComponentEnabledSetting(
compName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);

It's too late for answer, but maybe it will help someone.
I found different solution, like in accepted answer you can register receiver in your manifest, but instead of priority you can specify tools:node="remove" and this attribute will be removed from the resulting manifest. Also I think it's possible to create separate manifest for Android O.
<receiver android:name="com.package.app.SomeReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" tools:node="remove"/>
</intent-filter>
</receiver>

Related

Receiver for DownloadManager.ACTION_DOWNLOAD_COMPLETE in Manifest

Is it possible to listen for DownloadManager.ACTION_DOWNLOAD_COMPLETE in Manifest.xml?
All the examples I found use registerReceiver(downloadCompleteReceiver,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); from a class but I would like to receive it in Manifest.xml so I can listen when the app is closed.
I can't find this action when I try to set the intent-filter for my receiver in Manifest.xml
As the official documentation states:
Beginning with Android 8.0 (API level 26), the system imposes additional restrictions on manifest-declared receivers.
If your app targets Android 8.0 or higher, you cannot use the manifest to declare a receiver for most implicit broadcasts (broadcasts that don't target your app specifically). You can still use a context-registered receiver when the user is actively using your app.
From Is android.intent.action.DOWNLOAD_COMPLETE an explicit broadcast? we learn that android.intent.action.DOWNLOAD_COMPLETE seems to be an explicit broadcast, therefore there should be no issue defining a <receiver> for it in the manifest, even if it's not autocompleted. So just add it with an action of android.intent.action.DOWNLOAD_COMPLETE.
<receiver
android:name=".your.DownloadCompleteReceiver"
android:permission="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>

Android JobIntentService ADB Error: Requires permission android.permission.BIND_JOB_SERVICE

I'm trying to setup a JobIntentService and test it using adb.
When I use this command:
adb shell am startservice -a "com.example.package.action.DO_THING"
It produces the error:
Error: Requires permission android.permission.BIND_JOB_SERVICE
My AndroidManifest.xml has the following entry:
<service
android:name=".services.intents.IntentHandlerService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="com.example.package.action.DO_THING"/>
</intent-filter>
</service>
JobIntentService, like JobService, is only usable from within an app. You cannot have another app talk to those services, nor is there any sort of direct PendingIntent option.
(in theory, you might be able to talk to a JobIntentService from other apps on Android 4.4 and older, as I'm not certain how android:permission="android.permission.BIND_JOB_SERVICE" will be handled when that permission is undefined, but I wouldn't count on it)
For IPC, you will need to use something else. So, for example, if you want a PendingIntent to be processed by a JobIntentService, create a broadcast PendingIntent with an explicit Intent pointing to a manifest-registered receiver, and have it post the job to the JobIntentService.

Launch activity by dialing a number

I've created an appropriate BoradcastReceiver, registered it in Manifest.xml and here is my problem: if my application has already been launched and hanging in background, then dialing a number would bring it to front. If it has not been launched then dialing a number would have no effect.
How can I fix this? I test this on Xiaomi Mi4 with MIUI6 if that's important.
Here's the code (I use Scala):
manifest.xml:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
...
<receiver android:name="DialerGate" android:enabled="true" android:exported="true">
<intent-filter android:priority="1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
BroadcastReceiver:
class DialerGate extends BroadcastReceiver {
def onReceive(context: Context, intent: Intent) =
if (intent.getAction equals Intent.ACTION_NEW_OUTGOING_CALL) {
val phoneno = intent.getExtras getString Intent.EXTRA_PHONE_NUMBER
val prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
val number = prefs.getString(AbstractKit.LAUNCH_NUMBER, null)
Log.d("WALLET-PHONE", s"Dialed number: $phoneno, saved number: $number")
Log.d("WALLET-PHONE-OK", (number == phoneno).toString)
val i = new Intent
i.setClassName("com.app.wallet", "com.app.wallet.MainActivity")
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
val appContext = context.getApplicationContext
appContext.startActivity(i)
//if (number == phoneno) context startActivity new Intent(context, target)
//context stopService intent
}
}
From a simple user perspective, that cannot be done (its a security feature).
Starting from HONEYCOMB Android doesn't allow any broadcast receivers to be invoked until application is run at least once.
Its basically simpler to allow the program to be run at least once (during boot its the most common one), and then have the intent close the app if its not the time to use it.
Check this for further details on how to implement additional receivers that may do what you need it to do.
create a Listener in your Broadcast Receiver and listen to ON_BOOT_COMPLETED, then start your app, in silent mood and you will be resolved to your normal workings.
side note If Activities was to be waken up that way, then Keylogging apps and hacking apps will be very very very cheap to create - hence make android vulnerable.
http://android-developers.blogspot.in/2013/05/handling-phone-call-requests-right-way.html
Listening for outgoing call requests
Apps that provide phone calling services (such as VOIP or number management) can set up Intent filters to handle outgoing call requests, such as those made from the Dialer or other installed apps. This provides a seamless integration for the user, who can transition directly to the calling service without having to redial or launch another app.
When the user initiates a call, the system notifies interested apps by sending an ordered broadcast of the NEW_OUTGOING_CALL Intent, attaching the original phone number, URI, and other information as extras. This gives apps such as Google Voice and others a chance to modify, reroute, or cancel the call before it’s passed to the system’s default phone app.
If you want your phone calling app to be able to handle outgoing call requests, implement a broadcast receiver that receives the NEW_OUTGOING_CALL Intent, processes the number, and initiates a call as needed. Make sure to declare an intent filter for NEW_OUTGOING_CALL in the receiver, to let the system know that your app is interested in the broadcast. You’ll also need to request the PROCESS_OUTGOING_CALLS permission in order to receive the Intent.
Note that the system broadcasts NEW_OUTGOING_CALL only for numbers that are not associated with core dialing capabilities such as emergency numbers. This means that NEW_OUTGOING_CALL can not interfere with access to emergency services the way your use of CALL_PRIVILEGED might.
Here’s an example broadcast receiver declared in an app’s manifest file:
<manifest>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<application>
...
<receiver android:name=MyOutgoingCallHandler">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
...
</application>
</manifest>
And I am sure that <category android:name="android.intent.category.DEFAULT" /> will do the trick for you. check this question too for more details about category tag.here
You could try a few things.
Try using java, if not try the following.
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
...
<receiver android:name="DialerGate">
<intent-filter android:priority="2147483648">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
Changed priority and removed unnecessary stuff.
Also though I am good at Broadcast Receivers I don't have experience in Scala, so I can only suggest a few ideas. Remove the if statement. It is not required as you have already have an <intent-filter>. Also change the intent as in the paste bin code.
Have a look here.
You may use a service, but just care about one thing: when the app is closed the service get closed also because they are in a one thread, so the service should be on another thread in order fot it not to be closed
You can keep it alive with AlarmManager.
In the link there are also some samples :)
Hope it helps!
The application might not have the permissions to the "phone", either ask for permissions at runtime or go to application settings and enable all the permissions asked by the application.
This worked for me..

Can I start NotificationListenerService in code explicitly rather than it be started for me by the OS?

I have class derived from NotificationListenerService and it is getting created and started for me automatically when the app starts.
However I would like to lazily start the service later from an activity and not have it start automatically when the app starts. Is it possible to do this?
The manifest is:
<service android:name=".MyNotificationListener"
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>
NOTE that before NotificationListenerService can be used the user has to grant the app notification access via the setting. However if the intent filter is removed from the manifest then the app does not appear in the settings and thus the user is unable to grant permission, so without permission the service can't be started. Seems like the OS needs that intent filter to be there before it will display the app in the settings.
UPDATE:
The documentation for BIND_NOTIFICATION_LISTENER_SERVICE says:
Must be required by an NotificationListenerService, to ensure that
only the system can bind to it.
So I guess that means only the OS can start NotificationListenerService and nobody else can.
Yes. Create an Intent for the service then call startService.

BroadcatReceiver declared in manifest.xml not receiving LocalBroadcastManager intents

While it is possible to declare a 'Local' BroadcastReceiver via code so it receives intents published via a LocalBroadcastManager.Ex
LocalBroadcastManager.getInstance(this).registerReceiver(new FooReceiver(), new IntentFilter("foo_intent_filter"));
I wonder if it is possible to declare such receiver via the manifest.xml (cleaner) .
When I use the 'manifest way', the receiver is not 'receiving' the intents.
<receiver
android:name="FooReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="foo_intent_filter" />
</intent-filter>
</receiver>
Am I missing something? or the code-way is the only viable solution.
Thanks
I wonder if it is possible to declare such receiver via the manifest.xml (cleaner) .
First, that is not possible.
Second, registering in the manifest has little to do with it being "cleaner". It is to allow Android to instantiate the receiver on its own, so that you can respond to broadcasts when your process is not running. And, in the specific example that you cite, it is to allow any app on the system to send you a broadcast. Neither of those are relevant for LocalBroadcastManager.

Categories

Resources