B4A Library BroadcastReceiver

Hey,

I'm proud to announce another library of mine: BroadcastReceiver.

I will try to explain as hard as I can, as I didn't went in to deep in broadcasting and stuff.

So, the Android Operating System sends all kind of messages around where the normal users can't see thse. These are called Intents. Every intent has a special role in the Android OS. But the intents don't stay there, wandering around. This is where the BroadcastReceiver comes in. BroadcastReceivers picks up the intents that you need with an intentFilter. This way, you can start actions when something happens in your phone.
But not only can you receive intents, You can also send/broadcast your own intents in your phone, or even pass your own info to another app that it listening.

(please tell me if i'm somewhere wrong ;)) I only learned about broadcasting and intents through this library.

Let me give you an example.

When a SMS text message comes into your phone, the intent "android.provider.Telephony.SMS_RECEIVED" is raised and send "through" your phone. Your standard text application (or even ChompSMS, GoSMS PRO, ...) picks the intent up with a BroadcastReceiver, and displays the incoming message on the notification bar and inbox, etc.

But how does it work now with the BroadcastReceiver Lib?
No manually changing the Android Manifest file is needed!
You only need a service to start working. (and an activity of course to start your service)

In your service process globals, declare the BroadcastReceiver;

B4X:
Dim Broadcast As BroadcastReceiver
I hope you know what this does, otherwise, I recommend you to read Klaus' Beginners Tutorial.

In the service_create, we start by initializing the library.

B4X:
Broadcast.Initialize("BroadcastReceiver")
The parameter "BroadcastReceiver" is needed for calling a sub when an intent arrives. I will explain this later.

After the services has been created and the library has been initialized, we start setting up our receiver that will listen for intents. This is done in Service_start.

B4X:
Sub Sub Service_Start (StartingIntent As Intent)
        Broadcast.addAction("android.provider.Telephony.SMS_RECEIVED")
   Broadcast.addAction(Broadcast.SMS_RECEIVED)
   Broadcast.SetPriority(2147483647)
   Broadcast.registerReceiver("")
End Sub

- AddAction will add the intent you are listening for in a filter. So when a message comes in, "android.provider.Telephony.SMS_RECEIVED" is broadcasted and received.
- SetPriority sets the priority of the listening broadcast. The higher the value, the more important the incoming intent will be thus the quicker it will be called instead of other apps with a lower priority.
- registerReceiver starts your receiver and listening for intents/actions. You can add an extra addAction parameter to the filter.

Now you are done setting up your basic receiver, but now something should be called when a sub arrives: the onreceive method. This is called with the action string of the intent you are listening for.
As I mentionned before, under here starts with BroadcastReceiver, this is the eventname parameter you gave in earlier in the initialize method.

B4X:
Sub BroadcastReceiver_OnReceive (Action As String)
   ToastMessageShow(Action,False)
   'can only abort when sendOrderedbroadcast is called.
   Broadcast.AbortBroadcast
End Sub

The toastmessage, in this case will show android.provider.Telephony.SMS_RECEIVED if an sms has been received.
Next, we stop the broadcast with AbortBroadcast so no other applications will receive this intent. AbortBroadcast will only be called if the broadcast sended is an Ordered one. You can check this with:

B4X:
Broadcast.isOrderedBroadcast

This is basically IT for receiving broadcasts.
Now, there is 1 more thing you should know.

- You can send a broadcast in 2 ways.
1)
B4X:
sendBroadcast(Broadcast.SMS_RECEIVED)

2)
B4X:
sendOrderedBroadcast(Broadcast.SMS_RECEIVED,"android.permission.READ_PHONE_STATE")

Ofcourse instead of Broadcast.SMS_RECEIVED, you can put any string in there that you want.

The difference between these two is that when you send an ordered broadcast, the broadcast will be more accurate filtered on the android permission, and as I said, you can use AbortBroadcast on this one.
You could just open your Android Manifest File and see what permissions your app has.


There are still some more functions, but these are explained in the library itself.

If you want to find info about intents, you can find all of them here:
http://developer.android.com/reference/android/content/Intent.html

Some Intents can't be broadcasted only by the system itself.

In the attachements, you can find the library files and a working sample of BroadcastReceiver.


NOTE: I FORGOT TO CHANGE THE VERSION OF BROADCASTRECEIVER TO 2.0 IN THE IDE. SO THE IDE MIGHT SAY VERSION 1.0 IN THE LIBRARY TAB

Comments, critiques, feedback is welcome!
Have fun!
Tomas
 

Attachments

  • BroadCastReceiver1.0.zip
    285.2 KB · Views: 2,299
  • BroadcastReceiver2.0.zip
    5.1 KB · Views: 2,767
Last edited:

RichardBernard

Member
Licensed User
The intention is to find out when the OS has finished the countdown of being in "discoverable" mode. You know how you go:

B4X:
Sub btnAllowConnection_Click
   'this intent makes the device discoverable for 300 seconds.
   Dim i As Intent
   i.Initialize("android.bluetooth.adapter.action.REQUEST_DISCOVERABLE", "")
   i.PutExtra("android.bluetooth.adapter.extra.DISCOVERABLE_DURATION", 300)
   StartActivity(i)
   serial1.Listen
End Sub

Well, I need to find out when the period of being "discoverable" has ended after setting DISCOVERABLE_DURATION; regardless of having been connected or not.

I appreciate your help,
R
 
Last edited:

RichardBernard

Member
Licensed User
You should intercept the android.bluetooth.adapter.action.SCAN_MODE_CHANGED intent:

This is what I wrote, but it doesn't work:
B4X:
Sub Process_Globals
   Dim Broadcast As BroadCastReceiver
   Dim actionMSG As String
End Sub
Sub Service_Create
   Broadcast.Initialize("BroadcastReceiver")
End Sub

Sub Service_Start(StartingIntent As Intent)
ToastMessageShow("BroadcastReceiver started...",False)
   Broadcast.addAction("android.bluetooth.adapter.action.STATE_CHANGED")
    Broadcast.SetPriority(999)
    Broadcast.registerReceiver("")
End Sub

Sub Service_Destroy

End Sub

Sub BroadcastReceiver_OnReceive(Action As String)
    ToastMessageShow(Action,True)
    'can only abort when sendOrderedbroadcast is called.
    'Broadcast.AbortBroadcast
End Sub

I set the duration to 10s and after starting this service I do get my "BroadcastReceiver started..." confirmation but the BroadcastReceiver_OnReceive doesn't get called. What I am doing wrong? Am I supposed to set Permissions or something?

Another question, what does the library mean by "rec: 999 to -999":
B4X:
SetPriority (Priority As Int)
'Sets the priority.
'The higher the value, the more important the receiver will be thus the first it 'will be called.
'max: 2147483647
'rec: 999 to -999
'Priority:


R
 

RichardBernard

Member
Licensed User
It should be SCAN_CHANGED not STATE_CHANGED. You should also move it to Service_Create.

The priority is not important in this case. It is only important in ordered broadcasts.

Thanks, I fixed it but it still does not call BroadcastReceiver_OnReceive(Action As String).

Here's the service:
B4X:
#Region  Service Attributes 
   #StartAtBoot: False
#End Region

Sub Process_Globals
   Dim Broadcast As BroadCastReceiver
   Dim actionMSG As String
End Sub
Sub Service_Create
   Broadcast.Initialize("BroadcastReceiver")
   Broadcast.addAction("android.bluetooth.adapter.action.SCAN_MODE_CHANGED")
End Sub

Sub Service_Start(StartingIntent As Intent)
    Broadcast.SetPriority(2147483647)
    'Broadcast.registerReceiver("")
End Sub

Sub Service_Destroy

End Sub

Sub BroadcastReceiver_OnReceive(Action As String)
    'ToastMessageShow(Action,False)
   ToastMessageShow("BroadcastReceiver_OnReceive",True)
End Sub

Fyi, when I add either of the following the App crashes:
B4X:
Broadcast.registerReceiver("")
Broadcast.registerReceiver("android.bluetooth.adapter.action.SCAN_MODE_CHANGED")

:sign0085:
 

RichardBernard

Member
Licensed User

Wow, thanks for pointing out that BroadcastReceiver_OnReceive takes the second argument "i As Object" because the documentation does not indicate that at all!

Another question is why whether I call registerReceiver like:
B4X:
Broadcast.registerReceiver("")
Or
Broadcast.registerReceiver("android.bluetooth.adapter.action.SCAN_MODE_CHANGED")
it does not make any difference? I'm assuming because you can use registerReceiver to intercept another message, or I might be wrong...

R
 

bsnqt

Active Member
Licensed User
Hi Tomas,

I have updated the BroadcastReceiver 1.0 with 2.0. But B4A still shows it as only version 1.0 (see image attached).

I understand that version is nothing important (you may forget to change it before exporting the java files), but I post here to make sure I am not doing anything wrong as I don't know whether my library is already updated or not with the same version number.
 

Attachments

  • version.PNG
    version.PNG
    4.5 KB · Views: 88

kiki78

Active Member
Licensed User
Thank you for this library XverhelstX.

May you explain howto get Extras information with GetExtra ?

For example I'm connect to "android.hardware.usb.action.USB_DEVICE_DETACHED" action and as Extras, extract with ExtrasToSTring, I obtain :

Bundle[{device=UsbDevice[mName=/dev/bus/usb/002/006,mVendorId=1240,mProductId=63319,mClass=0,mSubclass=0,mProtocol=0,mInterfaces=[Landroid.os.Parcelable;@427c3e80]}]

I'm interested to parse VendorId and ProductId, but I never found howto use GetExtra to get it.
I see Bundle object in Android developer documentation, but not found equivalent in Basic4Android.

Regards
 

kiki78

Active Member
Licensed User
I never found any event in USB library to detect disconnection. Am I miss it ?

Regards
 

pfillion

Member
Licensed User
Hi,

I have a small problem. When I initialize the BroadcastReceiver library in my Service_Create and then register my receivers in Service_Start for "android.intent.action.HEADSET_PLUG" and "android.intent.action.DOCK_EVENT". As soon as the Service_Start finish, the BroadcastReceiver_OnReceive event triggers with events like HSET_STATE_UNPLUGGED and EXTRA_DOCK_STATE_UNDOCKED like 3 to 4 time each even if there are no headset plugged or device docked.

When I run the app multiple times, I always receive these messages even If no headset or dock have been plugged or unplugged since the last run. It just triggers BroadcastReceiver_OnReceive every time the receivers are registered.

Since I'm performing stuff on these 2 messages, is there a way to flush these messages ? or make sure that after initialization I don't receive these messages ? I was thinking of initializing a flag to just skip the code in BroadcastReceiver_OnReceive on first run but it's not really clean...
 

brelto85

Active Member
Licensed User
i'm trying to use this library to register a long press of headset button

i've write this code in the Service_Start

B4X:
Sub Service_Start (StartingIntent As Intent)
    Broadcast.addAction("android.intent.action.MEDIA_BUTTON")
    Broadcast.SetPriority(999)
    Broadcast.registerReceiver("")
End Sub

but it doesn't works when clicked (long press) headset button
starts always google search

How to make it work?

Alberto
 

Mauro

New Member
Licensed User
Thank you for this intresting library XverhelstX.
I have used the library with success.
But i have a question.
When i intercept the "android.intent.action.NEW_OUTGOING_CALL" intent and then in the OnReceive sub i want to end the call, this is not possible.
The only possibility (i guess) is to set the setResultData to null.
In the library there is a ResultData property but it is read only.
So my question is:
could you implement in the library a setResultData method?
 

viljemto

Member
Licensed User
Hi!

In Eclipse to end call, is to "return" before the function ends.

I am interested also to find out how to end call in B4A.

Viljem


Thank you for this intresting library XverhelstX.
I have used the library with success.
But i have a question.
When i intercept the "android.intent.action.NEW_OUTGOING_CALL" intent and then in the OnReceive sub i want to end the call, this is not possible.
The only possibility (i guess) is to set the setResultData to null.
In the library there is a ResultData property but it is read only.
So my question is:
could you implement in the library a setResultData method?
 

ppgirl

Member
Licensed User
Hi ,

I have a simple question - How to do "addDataScheme" ,

as Java code

installedReceiver = new MyInstalledReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.PACKAGE_ADDED");
filter.addAction("android.intent.action.PACKAGE_REMOVED");
filter.addDataScheme("package");
this.registerReceiver(installedReceiver, filter);

Thank in advance!
 
Top