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 );
Related
To put it simply; BroadcastReceiver Works when defined in Manifest but it works with a short Delay and it doesn't Always trigger unless Registered Manually.
Here is the BroadcastReceiver I created to capture event when date changes (day is passed):
public class BootBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, intent.getAction(), Toast.LENGTH_LONG).show();
switch (intent.getAction()){
case Intent.ACTION_TIME_TICK:
case Intent.ACTION_TIME_CHANGED:
case Intent.ACTION_TIMEZONE_CHANGED:
case Intent.ACTION_DATE_CHANGED:
case Intent.ACTION_BOOT_COMPLETED:
Log.d("BroadcastReceiver", intent.getAction().toString());
}
}
}
Here registered in Manifest, It works but has a short delay and also doesn't always trigger:
<receiver android:name=".Receivers.BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.TIME_TICK" />
<action android:name="android.intent.action.TIME_SET" />
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
But when registered manually via my background service it works just fine:
public class ApplicationService extends Service{
...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_DATE_CHANGED);
intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
intentFilter.addAction(Intent.ACTION_TIME_TICK);
registerReceiver(new BootBroadcastReceiver(), intentFilter);
return START_STICKY;
}
}
To investigate this issue further I created two similar app which in one BroadcastReceiver registered in Manifest and in the other one receiver is registered Manually via Service.
In the Manifest one all events are triggered few second after Manual one..
Try this :
<receiver android:name=".Receivers.BootBroadcastReceiver">
<intent-filter
android:enabled="true"
android:exported="true">
<action android:name="android.intent.action.TIME_TICK" />
<action android:name="android.intent.action.TIME_SET" />
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
I guess you can have multiple each one having its action.
https://developer.android.com/guide/components/intents-filters.html
The documentation says that "An app component should declare separate filters for each unique job it can do." This would allow finer grained detail for different actions
The answer was hidden in Intent documentation:
ACTION_TIME_TICK Added in API level 1
public static final String ACTION_TIME_TICK
Broadcast Action: The current time has changed. Sent every minute. You
cannot receive this through components declared in manifests, only by
explicitly registering for it with
Context#registerReceiver(BroadcastReceiver, IntentFilter).
To simply put, you can't receive TIME_TICK through registering the BroadcastReceiver in manifest, it has to be registered in your application components (Service, Activity, etc.)
Define a BootBroadcastReceiver anywhere in Activity/Fragment like this:
mBootBroadcastReceiver = new BootBroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG," BootBroadcastReceiver"); //do something with intent
}
};
mIntentFilter=new IntentFilter("action_name");
Now register the BootBroadcastReceiver in onResume() and Unregister in onPause()
#Override
protected void onResume() {
super.onResume();
registerReceiver(mBootBroadcastReceiver, mIntentFilter);
}
#Override
protected void onPause() {
if(mReceiver != null) {
unregisterReceiver(mBootBroadcastReceiver);
mBootBroadcastReceiver = null;
}
super.onPause();
}
add permission in your Manifest.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="ANDROID.PERMISSION.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
I used this permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
and the receiver is:
<receiver android:name=".auth.NotificationBroadcast" android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
and receiver in code is:
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("BroadcastReceiverBroadcast--------------------ReceiverBroadcastReceiverBroadcastReceiver----------------BroadcastReceiver");
if (intent != null) {
String action = intent.getAction();
switch (action) {
case Intent.ACTION_BOOT_COMPLETED:
System.out.println("Called on REBOOT");
// start a new service and repeat using alarm manager
break;
default:
break;
}
}
}
After reboot it's still not getting called in lollipop, but on marshmallow it's running.
try to put this line in your receiver's intent-filter.
<action android:name="android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE" />
If your application is installed on the SD card, you should register this to get the android.intent.action.BOOT_COMPLETED event.
Updated: Since your app is using alarm service, it should not be installed on external storage. Reference: http://developer.android.com/guide/topics/data/install-location.html
Whenever the platform boot is completed, an intent with android.intent.action.BOOT_COMPLETED action is broadcasted. You need to register your application to receive this intent. For registering add this to your AndroidManifest.xml
<receiver android:name=".ServiceManager">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
So you will have ServiceManager as broadcast receiver to receive the intent for boot event. The ServiceManager class shall be as follows:
public class ServiceManager extends BroadcastReceiver {
Context mContext;
private final String BOOT_ACTION = "android.intent.action.BOOT_COMPLETED";
#Override
public void onReceive(Context context, Intent intent) {
// All registered broadcasts are received by this
mContext = context;
String action = intent.getAction();
if (action.equalsIgnoreCase(BOOT_ACTION)) {
//check for boot complete event & start your service
startService();
}
}
private void startService() {
//here, you will start your service
Intent mServiceIntent = new Intent();
mServiceIntent.setAction("com.bootservice.test.DataService");
mContext.startService(mServiceIntent);
}
}
Since we are starting the Service, it too must be mentioned in AndroidManifest:
<service android:name=".LocationService">
<intent-filter>
<action android:name="com.bootservice.test.DataService"/>
</intent-filter>
</service>
When I tried this code, everything is working fine except, service is not getting start after device reboot. I want to start same service automatically. I am testing this example by connecting mobile with USB. what do I need to change ?
[http://javatechig.com/android/repeat-alarm-example-in-android]
try like this
<!-- for reboot event to reset alarms -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
then
<receiver
android:name="com.yourapp.receiver.RestartAppReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
next you have to create the BroadcastReceiver class
public class RestartAppReceiver extends BroadcastReceiver {
private static final String LOG_TAG = "RestartAppReceiver";
public RestartAppReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
String action = intent.getAction();
switch (action) {
case Intent.ACTION_BOOT_COMPLETED:
Log.i(LOG_TAG, "Start resetting alarms after reboot");
//restart what you need
Log.i(LOG_TAG, "Finish resetting alarms after reboot");
break;
default:
break;
}
}
}
}
You have to create a broadcast receiver that will listen for boot complete event and when that event is received start your service again
<receiver android:name=".Autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
create a class like this and add your code in onReceive method
public class Autostart extends BroadcastReceiver
{
public void onReceive(Context arg0, Intent arg1)
{
Log.i("Autostart", "**********started************");
}
}
I want to stop a running service when a usb is unplugged.
inside my activity onCreate I check the intent for its action
if (getIntent().getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
Log.d(TAG, "************** USB unplugged stopping service **********");
Toast.makeText(getBaseContext(), "usb was disconneced", Toast.LENGTH_LONG).show();
stopService(new Intent(this, myService.class));
} else {
init();
}
And inside my manifest I have another intent filter
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
And this intent filter as well which is being called.
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
But the detach is not being called.
Hmmm.. ACTION_USB_DEVICE_DETACHED is fired when a USB device (not the cable) is detached from the phone/tablet. This is not something you want.
I do not know if there is a straight forward API for detecting USB cable connections, but you can use ACTION_POWER_CONNECTED and ACTION_POWER_DISCONNECTED to accomplish your goal.
Use following filters for your receiver:
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
</intent-filter>
And in your receiver, you can check the state and implement the logic you want:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
switch(intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)) {
case 0:
// The device is running on battery
break;
case BatteryManager.BATTERY_PLUGGED_AC:
// Implement your logic
break;
case BatteryManager.BATTERY_PLUGGED_USB:
// Implement your logic
break;
case BATTERY_PLUGGED_WIRELESS:
// Implement your logic
break;
default:
// Unknown state
}
}
}
You need to register a BroadcastReceiver
BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
Log.d(TAG, "************** USB unplugged stopping service **********");
Toast.makeText(getBaseContext(), "usb was disconneced",
Toast.LENGTH_LONG).show();
stopService(new Intent(this, myService.class));
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(receiver, filter);
I am working in Android 2.1, and I want to detect when the headset is plugged in/taken out. I'm pretty new to android.
I think the way to do it is using a Broadcast receiver. I sublcassed this, and I also put the following in my AndroidManifest.xml. But do you have to register the receiver somehwere else, like in the activity? I'm aware there are lots of threads on this, but I don't really understand what they're talking about. Also, what's the difference between registering in AndroidManifest.xml versus registering dynamically in your activity?
<receiver android:enabled="true" android:name="AudioJackReceiver" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" >
</action>
</intent-filter>
</receiver>
And this was the implementation of the class (plus imports)
public class AudioJackReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.w("DEBUG", "headset state received");
}
}
I was just trying to see if it works, but nothing shows up when I unplug/plug in the headset while running the application.
EDIT: the documentation doesn't say this, but is it possible that this one won't work if registered in the manifest? I was able to get it to respond when I registered the receiver in one of my applications (or do you have to do that anyway?)
Just complementing Greg`s answer, here is the code that you need divided in two parts
Register the Service in the first Activity (here its called MainActivity.java).
Switch over the result of the ACTION_HEADSET_PLUG action in the BroadCastReceiver.
Here it goes:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private MusicIntentReceiver myReceiver;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myReceiver = new MusicIntentReceiver();
}
#Override public void onResume() {
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
registerReceiver(myReceiver, filter);
super.onResume();
}
private class MusicIntentReceiver extends BroadcastReceiver {
#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 is unplugged");
break;
case 1:
Log.d(TAG, "Headset is plugged");
break;
default:
Log.d(TAG, "I have no idea what the headset state is");
}
}
}
}
Here are two sites that may help explain it in more detail:
http://www.grokkingandroid.com/android-tutorial-broadcastreceiver/
http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html
You have to define your intent; otherwise it won't access the system function. The broadcast receiver; will alert your application of changes that you'd like to listen for.
Every receiver needs to be subclassed; it must include a onReceive(). To implement the onReceive() you'll need to create a method that will include two items: Context & Intent.
More then likely a service would be ideal; but you'll create a service and define your context through it. In the context; you'll define your intent.
An example:
context.startService
(new Intent(context, YourService.class));
Very basic example. However; your particular goal is to utilize a system-wide broadcast. You want your application to be notified of Intent.ACTION_HEADSET_PLUG.
How to subscribe through manifest:
<receiver
android:name="AudioJackReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
Or you can simply define through your application; but. Your particular request; will require user permissions if you intend to detect Bluetooth MODIFY_AUDIO_SETTINGS.
You need to enable the broadcast receiver and set the exported attribute to true:
<receiver
android:name="AudioJackReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>