Android Question Create a broadcast receiver when app loads using inline java

Jmu5667

Well-Known Member
Licensed User
Longtime User
Hi All

I have a app that uses a few intent filters. They are currently setup in manifest file. Example

B4X:
' // Power Intents
AddReceiverText(svc_power, <intent-filter> <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/></intent-filter>)
AddReceiverText(svc_power, <intent-filter> <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/></intent-filter>)

What I want to do is register these intent filters when the app loads. I came across this http://hmkcode.com/android-sending-receiving-custom-broadcasts/ , go to point 4.

B4X:
@Override
  protected void onResume() {
  super.onResume();
  registerReceiver(new MyReceiver(),
  new IntentFilter("com.hmkcode.android.USER_ACTION"));

  }


I do not want to use any existing libs. the app is quite complicated and due to customer requirements and our Bluetooth device
communicating with the app, www.ursosbutton.com, I need the manage the intent filter registration from within the app.

All help would be much appreciated, @Erel, @thedesolatesoul

Kind Regards

John.
 

Jmu5667

Well-Known Member
Licensed User
Longtime User
You don't need any java code for this. The service will be started when the intent is received.

Intent Filters - Intercepting SMS messages in the background
Hi Erel,

Lemonisdead is spot on. That's what I want to do. I already have intents filters set up and that are getting fired before I need them, I know this may seem strange to you but this real world stuff and it the way the app as evolved.

Most of our apps now are very different to when they were first created. We have a couple of thousand apps out there and the biggest problem users were having was the drain on the battery with the use of GPS/Bluetooth/Wifi and the phone not being able to achieve deep sleep. We have overcome most of these issues but need more control of the intent filter handling.

Hope this makes sense to you.

regards

John.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
I dont think its that easy (atleast from your link, there may be other ways).
You missed step 2 where you need to extend BroadcastReceiver that would require a java library.
I cant think of how to do it without a library (right now).

That was just one example I found. I have seen other java code that does this, so I don't think it's impossible, particularly with the advent of inline java in b4x :)
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
I've been working on disabling activities today, using the PackageManager class:
http://developer.android.com/refere...tEnabledSetting(android.content.ComponentName, int, int)

In the manifest all components - activities, services, broadcast receivers etc - are enabled by default, they can also explicitly be set to disabled.
The PackageManager allows you to change the 'enabled state' of any component in your application, overriding the state specified in the manifest.

So would a solution be to disable your broadcast receivers when they are not required and re-enable them when required?
A disabled broadcast receiver will receive no broadcasts.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
@Erel My understanding of the broadcast receiver is that all intent filters set are received back into the service/module that the broadcast receiver is being used from. I was using it but dropped it in favor of using the manifest file to directly call the necessary services associated with the intent filters. This means that I do not need code running to handle the intents.

@warwound I dont this this would help when the app is loading - eg. I use the following :

B4X:
' // Power Intents
AddReceiverText(svc_power, <intent-filter> <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/></intent-filter>)
AddReceiverText(svc_power, <intent-filter> <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/></intent-filter>)


' // BlueTooth intents
AddReceiverText(svc_bt_state, <intent-filter> <action android:name="android.bluetooth.adapter.action.STATE_CHANGED"/></intent-filter>)
AddReceiverText(svc_bt_disconnect, <intent-filter> <action android:name="android.bluetooth.device.action.ACL_DISCONNECTED"/></intent-filter>)
AddReceiverText(svc_bt_connected, <intent-filter> <action android:name="android.bluetooth.device.action.ACL_CONNECTED"/></intent-filter>)

I have a primary service that has the #StartAtBoot: True set. Now when the device boots up and turns of the Bluetooth, the Bluetooth intents get fired and the Bluetooth services get started. On some devices the svc_power service will get started before the Bluetooth services.

I know this may seem a bit mad to anyone who is reading this, but because of the nature of the app this intents are necessary.

Regards

John.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Take a look at the attached example.

In the manifest editor i add a BroadcastReceiver for the action android.intent.action.ACTION_POWER_CONNECTED.
The BroadcastReceiver is disabled by default in the manifest:

B4X:
AddReceiverText(svc_power, <intent-filter><action android:name="android.intent.action.ACTION_POWER_CONNECTED"/></intent-filter>)
SetReceiverAttribute(svc_power, android:enabled, "false")

svc_power logs the action of the starting intent and shows a toast if the starting intent action is android.intent.action.ACTION_POWER_CONNECTED:

B4X:
Sub Process_Globals

End Sub

Sub Service_Create

End Sub

Sub Service_Start (StartingIntent As Intent)
	Dim Action As String=StartingIntent.Action
	
	Select Action
		Case "android.intent.action.ACTION_POWER_CONNECTED"
			Log("action=android.intent.action.ACTION_POWER_CONNECTED")
			ToastMessageShow("svc_power started, action=android.intent.action.ACTION_POWER_CONNECTED", False)
	End Select
	
	StopService("")
End Sub

Sub Service_Destroy

End Sub

The Main activity code is:

B4X:
Sub Process_Globals
	'	see http://developer.android.com/reference/android/content/pm/PackageManager.html
	
	'	This component is in its default enabled state (as specified in its manifest). 
	Private ENABLED_STATE_DEFAULT As Int=0
	
	'	This component has been explicitly disabled, regardless of what it has specified in its manifest. 
	Private ENABLED_STATE_DISABLED As Int=2
	
	'	This component has been explicitly enabled, regardless of what it has specified in its manifest. 
	Private ENABLED_STATE_ENABLED As Int=1
	
	Private BROADCAST_RECEIVER_FULLY_QUALIFIED_NAME As String="b4a.example.svc_power$svc_power_BR"
End Sub

Sub Globals
	Private JavaObject1 As JavaObject
	Private Label1 As Label
	Private ToggleButton1 As ToggleButton
End Sub

Sub Activity_Create(FirstTime As Boolean)
	JavaObject1.InitializeContext
	Activity.LoadLayout("Main")
End Sub

Sub Activity_Resume
	UpdateUI
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub ToggleButton1_CheckedChange(Checked As Boolean)
	Dim EnabledState As Int
	
	If Checked Then
		EnabledState=ENABLED_STATE_ENABLED
	Else
		EnabledState=ENABLED_STATE_DISABLED
		'	as the broadcast receiver is disabled by default in the manifest, you could instead set the default value instead of disabled value:
		'	EnabledState=ENABLED_STATE_DEFAULT
	End If
	JavaObject1.RunMethod("setComponentEnabledSetting", Array As Object(BROADCAST_RECEIVER_FULLY_QUALIFIED_NAME, EnabledState))
	
	UpdateUI
End Sub

Sub UpdateUI
	Dim EnabledState As Int=JavaObject1.RunMethod("getComponentEnabledSetting", Array As Object(BROADCAST_RECEIVER_FULLY_QUALIFIED_NAME))
	
	Select EnabledState
		Case ENABLED_STATE_DEFAULT
			'	svc_power is disabled by default (in the manifest)
			Label1.Text="ENABLED_STATE_DEFAULT"
			ToggleButton1.Checked=False
		Case ENABLED_STATE_DISABLED
			Label1.Text="ENABLED_STATE_DISABLED"
			ToggleButton1.Checked=False
		Case ENABLED_STATE_ENABLED
			Label1.Text="ENABLED_STATE_ENABLED"
			ToggleButton1.Checked=True
		Case Else
			Label1.Text="EnabledState="&EnabledState&CRLF&"This state not anticipated..."
			ToggleButton1.Enabled=False
	End Select
End Sub

#If JAVA

import android.content.ComponentName;
import android.content.pm.PackageManager;

public int getComponentEnabledSetting(String fullyQualifiedClassName){
	ComponentName componentName = new ComponentName(this, fullyQualifiedClassName);
	return this.getPackageManager().getComponentEnabledSetting(componentName);
}

public void setComponentEnabledSetting(String fullyQualifiedClassName, int enabledState){
	ComponentName componentName = new ComponentName(this, fullyQualifiedClassName);
	this.getPackageManager().setComponentEnabledSetting(componentName, enabledState, PackageManager.DONT_KILL_APP);
}

#End if

Compile and install the example.
You'll see a Label display the text "ENABLED_STATE_DEFAULT", a ToggleButton will be unchecked.
The BroadcastReceiver is in it's default state - it is not enabled.
You can use the ToggleButton to change the BroadcastReceiver's state from 'default' to either 'enabled' or 'disabled'.

Connect your device to power and you'll see a Toast message if the BroadcastReceiver is enabled, otherwise you'll see nothing.

Martin.
 

Attachments

  • DynamicBroadcastReceiver.zip
    13.7 KB · Views: 579
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Take a look at the attached example.

In the manifest editor i add a BroadcastReceiver for the action android.intent.action.ACTION_POWER_CONNECTED.
The BroadcastReceiver is disabled by default in the manifest:

B4X:
AddReceiverText(svc_power, <intent-filter><action android:name="android.intent.action.ACTION_POWER_CONNECTED"/></intent-filter>)
SetReceiverAttribute(svc_power, android:enabled, "false")

svc_power logs the action of the starting intent and shows a toast if the starting intent action is android.intent.action.ACTION_POWER_CONNECTED:

B4X:
Sub Process_Globals

End Sub

Sub Service_Create

End Sub

Sub Service_Start (StartingIntent As Intent)
    Dim Action As String=StartingIntent.Action
   
    Select Action
        Case "android.intent.action.ACTION_POWER_CONNECTED"
            Log("action=android.intent.action.ACTION_POWER_CONNECTED")
            ToastMessageShow("svc_power started, action=android.intent.action.ACTION_POWER_CONNECTED", False)
    End Select
   
    StopService("")
End Sub

Sub Service_Destroy

End Sub

The Main activity code is:

B4X:
Sub Process_Globals
    '    see http://developer.android.com/reference/android/content/pm/PackageManager.html
   
    '    This component is in its default enabled state (as specified in its manifest).
    Private ENABLED_STATE_DEFAULT As Int=0
   
    '    This component has been explicitly disabled, regardless of what it has specified in its manifest.
    Private ENABLED_STATE_DISABLED As Int=2
   
    '    This component has been explicitly enabled, regardless of what it has specified in its manifest.
    Private ENABLED_STATE_ENABLED As Int=1
   
    Private BROADCAST_RECEIVER_FULLY_QUALIFIED_NAME As String="b4a.example.svc_power$svc_power_BR"
End Sub

Sub Globals
    Private JavaObject1 As JavaObject
    Private Label1 As Label
    Private ToggleButton1 As ToggleButton
End Sub

Sub Activity_Create(FirstTime As Boolean)
    JavaObject1.InitializeContext
    Activity.LoadLayout("Main")
End Sub

Sub Activity_Resume
    UpdateUI
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub ToggleButton1_CheckedChange(Checked As Boolean)
    Dim EnabledState As Int
   
    If Checked Then
        EnabledState=ENABLED_STATE_ENABLED
    Else
        EnabledState=ENABLED_STATE_DISABLED
        '    as the broadcast receiver is disabled by default in the manifest, you could instead set the default value instead of disabled value:
        '    EnabledState=ENABLED_STATE_DEFAULT
    End If
    JavaObject1.RunMethod("setComponentEnabledSetting", Array As Object(BROADCAST_RECEIVER_FULLY_QUALIFIED_NAME, EnabledState))
   
    UpdateUI
End Sub

Sub UpdateUI
    Dim EnabledState As Int=JavaObject1.RunMethod("getComponentEnabledSetting", Array As Object(BROADCAST_RECEIVER_FULLY_QUALIFIED_NAME))
   
    Select EnabledState
        Case ENABLED_STATE_DEFAULT
            '    svc_power is disabled by default (in the manifest)
            Label1.Text="ENABLED_STATE_DEFAULT"
            ToggleButton1.Checked=False
        Case ENABLED_STATE_DISABLED
            Label1.Text="ENABLED_STATE_DISABLED"
            ToggleButton1.Checked=False
        Case ENABLED_STATE_ENABLED
            Label1.Text="ENABLED_STATE_ENABLED"
            ToggleButton1.Checked=True
        Case Else
            Label1.Text="EnabledState="&EnabledState&CRLF&"This state not anticipated..."
            ToggleButton1.Enabled=False
    End Select
End Sub

#If JAVA

import android.content.ComponentName;
import android.content.pm.PackageManager;

public int getComponentEnabledSetting(String fullyQualifiedClassName){
    ComponentName componentName = new ComponentName(this, fullyQualifiedClassName);
    return this.getPackageManager().getComponentEnabledSetting(componentName);
}

public void setComponentEnabledSetting(String fullyQualifiedClassName, int enabledState){
    ComponentName componentName = new ComponentName(this, fullyQualifiedClassName);
    this.getPackageManager().setComponentEnabledSetting(componentName, enabledState, PackageManager.DONT_KILL_APP);
}

#End if

Compile and install the example.
You'll see a Label display the text "ENABLED_STATE_DEFAULT", a ToggleButton will be unchecked.
The BroadcastReceiver is in it's default state - it is not enabled.
You can use the ToggleButton to change the BroadcastReceiver's state from 'default' to either 'enabled' or 'disabled'.

Connect your device to power and you'll see a Toast message if the BroadcastReceiver is enabled, otherwise you'll see nothing.

Martin.
Awesome, I will try this tomorrow, thanks mate ;)
 
Upvote 0
Top