Android: BroadcastReceiver not getting called from my Service - android

I am new to Android Development. I have defined a test app with a service, where I declare a BroadcastReceiver for receiving Bluetooth events -
public class MyService extends Service
{
BluetoothEventsReceiver mBluetoothEventsReceiver = null;
#Override
public int onStartCommand(Intent i, int flags, int startId) {
// register the receiver to listen for Bluetooth Connected/Dis-connected events
if (mBluetoothEventsReceiver != null) {
mBluetoothEventsReceiver = new BluetoothEventsReceiver();
Log.e(TAG, "Register receiver=" + mBluetoothEventsReceiver);
IntentFilter intent = new IntentFilter("android.bluetooth.device.action.ACL_CONNECTED");
intent.addAction("android.bluetooth.device.action.ACL_DISCONNECTED");
getApplicationContext().registerReceiver(mBluetoothEventsReceiver, intent);
}
return super.onStartCommand(i, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
My BroadcastReceiver is defined as
public class BluetoothEventsReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
Log.e(TAG, "Received Event" + " ACTION_ACL_DISCONNECTED" );
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.e(TAG, "device=" + device);
} else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
Log.e(TAG, "Received Event" + " ACTION_ACL_CONNECTED" );
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.e(TAG, "device=" + device);
}
}
}
I start the Service from my Activity, and I expect the BroadcastReceiver to print log messages when I connect and disconnect Bluetooth headset, but no logs are printed. So, I guess its not called.
public class MyActivity extends Activity {
// Debugging
public final static String TAG ="MyActivity";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.e(TAG, "Starting service");
startService(new Intent(".MyService"));
}
Also, when I add the receiver to the Manifest file, then the BluetoothEventsReceiver is invoked. But from my understanding, I do not need to declare the receiver in the Manifest file, if I want the receiver to be active only when the Service is running.
I do have the permissions set in the Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:label="#string/app_name">
<activity android:name="MyActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name=".MyService" android:process=":remote">
<intent-filter>
<!-- These are the interfaces supported by the service, which
you can bind to. -->
<action android:name=".MyService" />
</intent-filter>
</service>
</application>
</manifest>
Please help debug what I am doing wrong.

change your intent filter from this:
IntentFilter intent = new IntentFilter("android.bluetooth.device.action.ACL_CONNECTED");
intent.addAction("android.bluetooth.device.action.ACL_DISCONNECTED");
to this:
IntentFilter intent = new IntentFilter();
intent.addAction("android.bluetooth.device.action.ACL_CONNECTED");
intent.addAction("android.bluetooth.device.action.ACL_DISCONNECTED");
It seems that the filter that you created doesn't match to bluetooth intents as they do have extra data attached while your filter works only for empty intents having only an action.
Here is the javadoc for the API:
public IntentFilter (String action)
Since: API Level 1
New IntentFilter that matches a single action with no data. If no data characteristics are subsequently specified, then the filter will only match intents that contain no data.

This startService(new Intent(".MyService")) won't work. You need to provide the actual path of the Service class name. Relative path is only used in AndroidManifest file, it should not be used in codes.
Try something like this in your activity:
Intent intent = new Intent(this, MyService.class);
this.startService(intent);
where MyService refers to the actual fully-qualified name of your service.

Related

android: Headset plug listener

public class HeadsetIntentReceiver extends BroadcastReceiver {
private String TAG = "HeadSet";
public HeadsetIntentReceiver() {
Log.d(TAG, "Created");
}
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
switch(state) {
case(0):
Log.d(TAG, "Headset unplugged");
break;
case(1):
Log.d(TAG, "Headset plugged");
break;
default:
Log.d(TAG, "Error");
}
}
}
}
Here's my code for listening for headphone plug, I initiated this from a Service class, but every time I plug and unplug it, nothing appears on the Logcat, any ideas?
AndriodManifest.xml
<service android:name="com.jason.automator.HeadphoneJackListenerService" />
<receiver android:name=".HeadsetIntentReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
If the minimum SDK version of your application is LOLLIPOP, it is recommended to refer to the AudioManager constant AudioManager.ACTION_HEADSET_PLUG in your receiver registration code instead.
If you haven't registered your receiver in manifest you can do like below
<receiver android:name=".HeadsetIntentReceiver" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
Also you can register it dynamically.
When OS send this "HEADSET_PLUG" intent, OS set the flag "Intent.FLAG_RECEIVER_REGISTERED_ONLY" . That's why may be your code not working. So try registering dynamically like below in Activity or Service class instead of "AndroidManifest" things.
So try below code,
IntentFilter receiverFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
HeadsetIntentReceiver receiver = new HeadsetIntentReceiver();
registerReceiver( receiver, receiverFilter );

Android : How to execute code when bluetooth connection disconnected to particular device

I wanna know how to execute a particular code when my fone's bluetooth device is connected to any device and also i want to execute another code when my fone disconnects from that bluetooth connection?
Please provide the code with proper comments.
You can create a BroadcastReceiver to handle that:
In on manifest.xml:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<receiver android:name=".MyBluetoothReceiver" >
<intent-filter>
<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" />
</intent-filter>
</receiver>
Write class MyBluetoothReceiver derived from BroadcastReceiver. Override the onReceive method and for each action implement your code:
public class MyBluetoothReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(
"android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED")){
// code for Bluetooth connect
}
if(intent.getAction().equals(
"android.bluetooth.device.action.ACL_DISCONNECTED")){
//code for Bluetooth disconnect;
}
}
}
Here's the proper answer I found :
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//you can get name by device.getName()
} else if (BluetoothAdapter.ACL_DISCONNECTED
.equals(action)) {
}
}
};

Monitoring network connection type change in Android Service

I want to capture the network connection type change in Android Service and run a code of this Service when the event fires. How to do that inside a Service class only without separate class? I have this code, but it doesn't work.
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
playlist="NETWORK TYPE CHANGED";
}
};
public void playSong(Context c, String url) {
try
{
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkStateReceiver, filter);
Your BroadcastReceiver needs to receive the Intent from the system, so you need to register your BroadcastReceiver in your AndroidManifest
<receiver
android:name=".ConnectivityReceiver
android:exported="false" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
and do not forget the permission
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Android Boot-Up BroadCast Not invoking

I am currently trying to make a broadcast receiver which will invoke after android device boots and then will run a background service. I have tried many examples but don't know where I'm going wrong. I am following this example:
https://github.com/commonsguy/cw-advandroid/tree/master/SystemEvents/OnBoot
I have imported this whole project in my workspace and tried to run. But the receiver didn't invoked or so.
Please help me out.
My Testing Device is: Motorolla Xoom with ICS 4.0.3
EDIT
Manifest
<uses-sdk android:minSdkVersion="8" />
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REBOOT" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<service
android:name="awais.soft.MyService"
android:enabled="true" >
<intent-filter>
<action android:name="awais.soft.MyService" >
</action>
</intent-filter>
</service>
<receiver android:name="awais.soft.ServicesDemoActivity" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" >
</action>
<category android:name="android.intent.category.HOME" >
</category>
</intent-filter>
</receiver>
</application>
Broadcast Receiver
package awais.soft;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
public class ServicesDemoActivity extends BroadcastReceiver {
static final int idBut = Menu.FIRST + 1, idIntentID = Menu.FIRST + 2;
#Override
public void onReceive(Context context, Intent intent) {
Log.e("Awais", "onReceive:");
if (intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)) {
Intent i = new Intent();
i.setAction("awais.kpsoft.MyService");
context.startService(i);
}
}
}
Service
package awais.soft;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
player = MediaPlayer.create(this, R.raw.is);
player.setLooping(false); // Set looping
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
player.stop();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
player.start();
}
}
I am something like this in My app and Its Working for me.
public class DeviceBootReceiver extends BroadcastReceiver {
#Override
public final void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
// CustomLog.i("Boot Completed");
}
}
}
Android Manifset
<receiver android:name=".model.service.DeviceBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
<category android:name="android.intent.category.HOME"></category>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<uses-permission android:name="android.permission.REBOOT" />
Please check if you have given permission for RECEIVE_BOOT_COMPLETED
see i am posting you eample that will help you
For some applications, you will need to have your service up and running when the device is started, without user intervention. Such applications mainly include monitors (telephony, bluetooth, messages, other events).
At least this feature is currently allowed by the exaggeratedly restrictive Android permissions policy.
Step 1: First you'll need to create a simple service, defined in Monitor.java:
public class Monitor extends Service {
private static final String LOG_TAG = "::Monitor";
#Override
public void onCreate() {
super.onCreate();
Log.e(LOG_TAG, "Service created.");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.e(LOG_TAG, "Service started.");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e(LOG_TAG, "Service destroyed.");
}
#Override
public IBinder onBind(Intent intent) {
Log.e(LOG_TAG, "Service bind.");
return null;
}
}
Step 2: Next we need to create a Broadcast receiver class, StartAtBootServiceReceiver.java:
public class StartAtBootServiceReceiver extends BroadcastReceiver
{
private static final String LOG_TAG=StartAtBootServiceReceiver";
#Override
public void onReceive(Context context, Intent intent)
{
Log.e(LOG_TAG, "onReceive:");
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent i = new Intent();
i.setAction("test.package.Monitor");
context.startService(i);
}
}
}
Step 3: Finally, your AndroidManifest.xml file must contain the following:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.package.Monitor"
android:versionName="1.0"
android:versionCode="100"
android:installLocation="internalOnly">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="8"/>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<service android:name="test.package.Monitor">**
<intent-filter>
<action android:name="test.package.Monitor">
</action>
</intent-filter>
</service>
<receiver android:name="test.package.StartAtBootServiceReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED">
</action>
<category android:name="android.intent.category.HOME">
</category>
</intent-filter>
</receiver>
</application>
I need to highlight some of the most important aspects, key factors for possible errors in implementation:
1) The permission android.permission.RECEIVE_BOOT_COMPLETED must be provided (in the manifest xml)
2) The installation must be performed in internal storage, not on SDCARD! To enforce this use android:installLocation="internalOnly" in the manifest
Everything was fine..:S
The problem was with device..(i.e. Motorolla Zoom ICS 4.0.3)
Now tested on Galaxy Tab With 2.2 and Working fine..
Thanks all for your time
If your phone is rooted then you will have trouble in Android Boot-Up BroadCast invoking otherwise you have to ensure your app has required root permissions
The problem persists in the case of devices having android version more than 3.0, by the way its not the problem it has been done for security purposes by google i guess..If u have to run the service on boot you have to make a custom intent & broadcast it. For making custom intent you have to make a service file from where u have to broadcast that intent on boot complete & your service file(that u want to run) will receive that intent on its onReceive method & your service will run.One more thing the service file you will create to call your service that you want to run should be kept on system/app folder of file explorer of device, if your file system shows sorry read only file system then from command prompt do just adb remount & then push the file on device,restart your system your service will run..Cheers!!

Listen incoming calls through BroadcastReceiver, without PhoneStateIntentReceiver or PhoneStateListener

Is there any way to listen to incoming calls by extending BroadcastReceiver to listen to OS's broadcast,without using PhoneStateIntentReceiver or PhoneStateListener.
Also please tell me what will be action and permissions in manifest.
I've tried with as follows but it is not working for incoming calls but working for outgoing
The only one .java file of app is as follows(the app only one .java file and one manifest file)
package com.crsardar.media.audio;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class IncommingCallReceiverCRS extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.e("Chitta : ", "Its working");
}
}
manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.crsardar.media.audio"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name="IncommingCallReceiverCRS" android:enabled="true">
<intent-filter>
<!--action android:name="android.intent.action.NEW_OUTGOING_CALL"/-->
<action android:name="android.intent.action.ANSWER" >
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
</manifest>
The action you have defined in your manifest is incorrect. this is an Action Intent that can be used to answer a call and not monitor incoming calls.
You can use two broadcast receivers that listen to ACTION_PHONE_STATE_CHANGED and NEW_OUTGOING_CALL broadcast intents.
The ACTION_PHONE_STATE_CHANGED will be received when there is a new incoming call, call answered or hangup (See the documentation for the EXTRAs received with this Intent).
The NEW_OUTGOING_CALL will be received when there is a new outgoing call placed on your device.
As for permissions, I think you got it about right in your manifest (I assume the RECORD_AUDIO permission is used for something else in your application)
Here is My demo for android unit test. You can refer to it.
public interface ICallVerify {
void onOutgoing(Context context, Intent intent);
void onCallStateChange(Context context, Intent intent);
}
protected void setUpCallVerify(final ICallVerify callVerify) { //listen ingoing and outgoing
final CountDownLatch latch = new CountDownLatch(1);
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) { //state change
Log.i(TAG, "outgoing call...");
callVerify.onOutgoing(context, intent);
} else if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)){ // state changed
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals("RINGING")) {
state += " number:" + intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
}
Log.i(TAG, "call state changed.... " + state);
callVerify.onCallStateChange(context, intent);
}
}
};
IntentFilter filter = new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
filter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
ContextUtils.getTargetContext().registerReceiver(receiver, filter);
try {
latch.await(5, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Dont forget to add permissions
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses-permission>

Categories

Resources