How do we specify in broadcast sending application that which application can receive this broadcast, and in receiving application that which particular application has the permission to send broadcast to its broadcast receiver...
I am new to android..I read the documentation etc on internet but couldn't find the syntax to specify these permissions.
To control who is able to receive the broadcast message, you can use the method sendBroadcast:
public abstract void sendBroadcast (Intent intent, String receiverPermission)
where you precise the name of the required permission. If the receiver does not declare this permission, it will not be able to get the message. For example, the broadcast sender can do:
Intent broadcast = new Intent(this, MyBroadcastReceiver.class);
sendBroadcast(broadcast, "andro.jf.mypermission");
In the manifest of the broadcast sender, a new permission should be declared:
<!-- Declaring the special permission -->
<permission android:name="andro.jf.mypermission"
android:label="my_permission"
android:protectionLevel="dangerous"></permission>
Then, in the application that is supposed to receive this broadcast, you have to declare this permission and say that you use it. In the manifest you can add:
<!-- I use the permission ! -->
<uses-permission android:name="andro.jf.mypermission"/>
and of course, you have to declare your broadcast receiver:
<receiver android:name="MyBroadcastReceiver" android:exported="true" />
You can have a look at this post for a complete example of a custom permission and also the android developer page about this. Be carefull with the order of installation of your apps because the one that defines the permission should be installed first.
If you want to restrict who only can send intents to your broadcast receiver, do it this way:
The broadcast receiver:
<manifest ...>
<!-- Permission declaration -->
<permission android:name="my.app.PERMISSION" />
<receiver
android:name="my.app.BroadcastReceiver"
android:permission="my.app.PERMISSION"> <!-- Permission enforcement for delivering intents to this receiver -->
<intent-filter>
<action android:name="my.app.Action" />
</intent-filter>
</receiver>
...
</manifest>
The broadcast sender:
<manifest ...>
<!-- We declare we own the permission to send broadcast to the above receiver -->
<uses-permission android:name="my.app.PERMISSION" />
...
</manifest>
Sending broadcast from the sender Activity to the receiver:
Intent intent = new Intent();
intent.setAction("my.app.Action");
activity.sendBroadcast(intent);
If you declare the permission like this:
<permission android:protectionLevel="signature" android:name="my.app.PERMISSION" />
Then the sender will be able to use this permission and send broadcasts to receiver only when both the sender and the receiver apps are signed by the same developer certificate.
Declare permission
First you need declare your permission in your AndroidManifest.xml
<permission android:name="YOUR_PERMISSION_STRING" android:protectionLevel="signature"/>
<uses-permission android:name="com.codylab.photogallery.PRIVATE"/>
the android:name value is used as permission value and will used later.
Usage
There are two kinds of permission usages related to broadcast receiver:
(1) Control which application can receive your broadcast:
String PERMISSION_STRING_PRIVATE_RECEIVER = "YOU_NEED_THIS_TO_RECEIVE_THIS_BROADCAST"
sendBroadcast(intent, PERMISSION_STRING_PRIVATE_RECEIVER);
With this usage, you can control only authorized application can handle the broadcast you sent.
(2) Only handle the broadcasts have the specified permission
String PERMISSION_STRING_PRIVATE_BROADCASTER = "ONLY HANDLE BROADCASTS WITH THIS PERMISSION"
IntentFilter filter = new IntentFilter(ACTION_SAMPLE);
registerReceiver(mReceiver, filter, PERMISSION_STRING_PRIVATE_BROADCASTER, null);
With this usage, you can make sure that the broadcaster is authorized.
use an intent filter in receiver tag in manifest
<receiver
android:name="Your receiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="action"/>
<category android:name="category" />
</intent-filter>
</receiver>
To send broadcast to app
Intent intent = new Intent();
intent.setAction("use same action in receiver");
intent.addcategory("use same category in receiver");
context.sendBroadcast(intent);
After half day search and test, based on #JFL's answer, I find the sender app must add both <permission> tag and <uses-permission> tag, then the receiver can receive the broadcast with permission. Otherwise, the receiver app won't receive the broadcast.
Related
In my first application, I define a custom permission and an implicit BroadcastReceiver in manifest file:
<permission
android:name="com.example.test.TEST"
android:protectionLevel="signature" />
<receiver
android:name=".TestBroadcastReceiver"
android:enabled="true"
android:exported="true"
android:permission="com.example.test.TEST">
<intent-filter>
<action android:name="com.example.test.TEST_RECEIVER" />
</intent-filter>
</receiver>
And this is the TestBroadcastReceiver.java:
public class TestBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Test", "Hello World!");
Toast.makeText(context, "Hello World!", Toast.LENGTH_LONG).show();
}
}
In my second app, I've added the permission in manifest file:
<uses-permission android:name="com.example.test.TEST" />
And here, I send the broadcast:
getActivity().sendBroadcast(new Intent("com.example.test.TEST_RECEIVER"));
But nothing is called in first app. I know we can't use implicit broadcast in android O and above but according to here, there is an exception for broadcasts that require a signature permission:
Broadcasts that require a signature permission are exempted from this
restriction, since these broadcasts are only sent to apps that are
signed with the same certificate, not to all the apps on the device.
So how can I signal my other apps in android O?
According to CommonsWare answer, the problem is that I was missing setPackage() part. So I changed the code as below and now broadcast is received:
getActivity().sendBroadcast(new Intent("com.example.test.TEST_RECEIVER").setPackage("com.example.test"));
I need a Broadcast Receiver name "NetworkReciver.java" that should execute when Internet is Connected or Disconnected. But it is noit executing.
Manifest permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<receiver android:name=".NetworkReciever" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
In MainActivity.java requested permissions
String[] permissionsRequired = new String[]{Manifest.permission.SET_ALARM,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE,};
// Since these are Normal Permissions
ActivityCompat.requestPermissions(this, permissionsRequired, 1);
NetworkReciever.java:
public class NetworkReciever extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.i("KAMLESH", "Network REceiver Alarm Set in Hair Style");
}
}
you must register NetworkReciever this broadcast receiver like registerReceiver(new NetworkReciever()); in any activity
From documentation
Apps targeting Android 7.0 (API level 24) and higher do not receive CONNECTIVITY_ACTION broadcasts if they declare the broadcast receiver in their manifest. Apps will still receive CONNECTIVITY_ACTION broadcasts if they register their BroadcastReceiver with Context.registerReceiver() and that context is still valid.
It means you need to register your receiver dynamically, not from manifest. Read Dynamically register/unregister a broadcast receiver in android which will give you the idea about dynamic way.
NOTE : The CONNECTIVITY_ACTION is deprecated since API 28. There are few other options introduced and you can find in the same url CONNECTIVITY_ACTION
So I have 2 apps - A and B.
In A i have a BroadcastReceiver. In the receiver tag (manifest file) I specify an android:permission string (let's say com.example.app.SEND). Now B cannot send broadcasts to A anymore. Makes sense!
So what do I have to do in order for B to send broadcasts to A ? In B's manifest, I specified uses-permission tag with android:name set to the same string (com.example.app.SEND) as the receiver's android:permission but still the broadcasts won't go from B to A.
What am I doing wrong ? Or is there something else that needs to be done ?
-- Update --
Here's my app A's receiver tag:
<receiver
android:name="com.example.app.MyReceiver"
android:enabled="true"
android:exported="true"
android:permission="com.example.BReceiver.SEND" >
<intent-filter>
<action android:name="com.example.BReceiver" />
</intent-filter>
</receiver>
And here's the uses-permission tag from my B's manifest:
<uses-permission android:name="com.pycitup.BReceiver.SEND" />
So I'd to set a custom permission for the same string like this in B's manifest:
<permission android:name="com.pycitup.BReceiver.SEND" />
Was quite straight-forward and simple. Just required a bit of reading across the web.
From B create an intent and set the action to your broadcast receivers name.
Intent myintentB=new Intent();
myintentB.setAction("com.example.app.SEND");
sendBroadcast(myintentB);
This should technically hit your receiver.
I am trying to make an app that shows a toast when the device's Bluetooth turned on. I wanna do that even when my app is not running. So I should use a broadcast receiver, add some permissions, an intent-filter to android manifest and make a java class but I don't know the details.
What should I do? Which permissions should I use?
AS far as permissions go, to detect the state change of bluetooth you need to add this to your AndroidManifest.xml.
<uses-permission android:name="android.permission.BLUETOOTH" />
An example receiver would look like this, you add this code to where you want to handle the broadcast, for example an activity:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive (Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
if(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
== BluetoothAdapter.STATE_OFF)
// Bluetooth is disconnected, do handling here
}
}
};
To use the receiver, you need to register it. Which you can do as follows. I register the receiver in my main activity.
registerReceiver(this, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
You could also decide to add all of it to your AndroidManifest.xml. This way you can make a special class for the receiver and handle it there. No need to register the receiver, just make the class and add the below code to the AndroidManifest
<receiver
android:name=".packagename.NameOfBroadcastReceiverClass"
android:enabled="true">
<intent-filter>
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED"/>
</intent-filter>
</receiver>
You have to take following permission.
<uses-permission android:name="android.permission.BLUETOOTH" />
and you have to write this as your intent filter in receiver tag.
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
Unfortunately, for apps targeting api 26 or higher, manifest declared broadcast receivers don't work anymore (reference here: https://developer.android.com/guide/components/broadcast-exceptions), with some exceptions.
android.bluetooth.adapter.action.STATE_CHANGED is not in that list.
For bluetooth, you can only listen for changes on:
ACTION_CONNECTION_STATE_CHANGED, ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECTED
I'm currently trying to catch states for ACTION_SCO_AUDIO_STATE_CHANGED as specified by:
http://developer.android.com/reference/android/media/AudioManager.html#ACTION_SCO_AUDIO_STATE_CHANGED
I have registered the intent on my manifest but I'm not getting anything when connecting to a bluetooth device. Any particular permission I need or something?
Manifest:
<receiver android:name="com.app.receiver.BluetoothReceiver">
<intent-filter>
<action android:name="android.media.SCO_AUDIO_STATE_CHANGED" />
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
<action android:name="android.bluetooth.device.action.BOND_STATE_CHANGED" />
</intent-filter>
</receiver>
I can't get any of the calls from BOND_STATE_CHANGED, SCO_AUDIO_STATE_CHANGED or ACL_DISCONNECT_REQUESTED. The other intents I'm receiving them just fine.
Thanks,
-Jona
It's probably a broadcast intent that cannot be received using the Manifest. You'll have to setup a BroadcastReceiver object and register it to receive the broadcast. The Receiver must be active in order to receive the intent.
Some broadcasts intents work like this while others are allowed to be caught via the manifest.
The other possibility is that the receiver requires a permission that you aren't requesting.
This is an important note from the SDK about Context.registerReceiver().
Note: this method cannot be called from a BroadcastReceiver component; that is, from a BroadcastReceiver that is declared in an application's manifest. It is okay, however, to call this method from another BroadcastReceiver that has itself been registered at run time with registerReceiver(BroadcastReceiver, IntentFilter), since the lifetime of such a registered BroadcastReceiver is tied to the object that registered it
<uses-permission android:name="android.permission.BROADCAST_STICKY"