I want to stop the currently running MusicPlayer when the user unplugs the headphones (both wired & bluetooth).
I came across sevral posts where use of:
isWiredHeadsetOn(), isBluetoothA2dpOn()
is suggested.
But Android docs says isWiredHeadsetOn() is deprecated. What alternative should I use?
Thanks
From the docs:
isWiredHeadsetOn() - This method is deprecated. Use only to check is a headset is connected or not.
It sounds like it is still recommended for what you're doing, though the docs are worded poorly
I just read a post where someone was suggesting registering for the ACTION_HEADSET_PLUG broadcast event.
You can apparently get the state of it from: intent.getIntExtra("state", 0));
I use AudioManager.ACTION_AUDIO_BECOMING_NOISY event in my app.
Create your custom broadcast receiver:
private class HeadsetIntentReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context cntx, Intent intent)
{
String action = intent.getAction();
if(action.compareTo(AudioManager.ACTION_AUDIO_BECOMING_NOISY) == 0)
{
}
}
}; /* end HeadsetIntentReceiver */
Then register receiver:
headsetReceiver = new HeadsetIntentReceiver();
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
mParentActivity.registerReceiver(headsetReceiver, mIntentFilter);
Don't forget to unregister it later.
According to the documentation for it, it's deprecated but suggested to be used ONLY for checking to see if a headset is connected or not. Should be fine to use.
Related
I am trying to understand how broadcast receiver works internally.
What happens internally when I call registerReceiver() method? Does it create a service internally ?
What happens internally when I call sendBroadcast?
If I have to implement my own BroadcastReceiver class (without extending the Android BroadcastReceiver class) how can I achieve it?
I did a lot of research, but I only found how BroadcastReceiver works. I looked at the Android source code too to find out how it works, but it didn't help either.
You wrote that you need to implement a BroadcastReceiver without extending Android BroadcastReceiver. This is not possible. The Android framework handles the dispatching and delivery of all broadcast Intents to all components that have registered themselves as being listeners for those Intents. When some application calls sendBroadcast(), Android checks if any BroadcastReceivers have registered as listener for that Intent and if it finds any, it instantiates the component (if it isn't already instantiated) and then calls the component's onReceive() method.
If you don't extend Android's BroadcastReceiver you cannot register your component as a listener and Android will not call your class' onReceive().
NOTE: Please explain what it is you really want to do if you want more help.
I'm not an expert in Android... but expert in everything else :P haha just kidding, i think that a BroadcastReceiver it's like a kind of (linux) crontab, it seems like Android already have some kind of piece of software (or internal service) running for this, and when you use it... you "program it" (to that "service") with selected filters and stuff, that's why is being called even if your app isn't running. OR MAYBE i'm TOTALLY WRONG :) but that's how i see it.
First of all:
import android.content.BroadcastReceiver;
Declare your Broadcast Receiver:
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Stuff you want to do when it receives something
}
};
And finally create an intent filter with the Intents you want your Broadcast to read:
IntentFilter iF = new IntentFilter(); // Example with some music players
iF.addAction("com.android.music.metachanged");
iF.addAction("com.htc.music.metachanged");
iF.addAction("fm.last.android.metachanged");
iF.addAction("com.sec.android.app.music.metachanged");
iF.addAction("com.nullsoft.winamp.metachanged");
iF.addAction("com.amazon.mp3.metachanged");
iF.addAction("com.miui.player.metachanged");
iF.addAction("com.real.IMP.metachanged");
iF.addAction("com.sonyericsson.music.metachanged");
iF.addAction("com.rdio.android.metachanged");
iF.addAction("com.samsung.sec.android.MusicPlayer.metachanged");
iF.addAction("com.andrew.apollo.metachanged");
iF.addAction("com.spotify.mobile.android.metadatachanged");
iF.addAction("com.spotify.music.metadatachanged");
registerReceiver(mReceiver, iF); // At the end you call your receiver with your intent Filter
Hope it helps
I'm developing an application for Android.
I use Samsung Galaxy S3 with original ROM Jelly Bean 4.3.
I have a problem with the receivers of incoming call and outgoing call.
Here is the code of IncomingCallReceiver:
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
if (Start.getMusicService().isPlaying()) {
pauseMusicService();
isMusicPlaying = true;
}
}
else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
if (isMusicPlaying){
restartMusicService();
isMusicPlaying = false;
}
}
}
However this is not the problem, this code works and also the outgoing call receiver works perfectly.
My problem is that when i exit the application this receivers still work.
It's happened that, days after the last time i opened the application, i received a phone call and the application crashed.
I think that it's happened because i write the code:
if (Start.getMusicService().isPlaying())
because Start (my first activity) doesn't exist.
I never register this receiver, they work without that i "call" them.
I don't know if i have to unregister and in case when i have to do it.
So, can anyone help me please?
Andrea
When declaring a BroadcastReceiver or other Intent receiver in your AndroidManifest it is always "on". Move the registration and deregistration to the beginning and end of the execution of your app, or other times in your app; then you will be able to control when its on at runtime.
Above answer is correct. If you want to register and/or unregister receiver yourself at you should register in onResume and unregister in onPause in case of activity. Look out this example http://sohailaziz05.blogspot.com/2012/05/broadcast-receiver-two-ways-to.html
Trying to get NFC to work on Android in Embarcadero XE5.
Started with the following: https://forums.embarcadero.com/thread.jspa?threadID=97574
which seem to be working. Now would like to register callback for the NFC Intent
Java approach:
1. Register current activity as a listener
...
2. Receive Intent
#Override
protected void onNewIntent(Intent intent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
NdefMessage[] msgs = NfcUtils.getNdefMessages(intent);
}
}
Source: http://www.jessechen.net/blog/how-to-nfc-on-the-android-platform/
Delphi approach (as I would imagine):
1. Define methods available in Java interface
Source: https://forums.embarcadero.com/thread.jspa?messageID=634212
Question:
How do I register a listener for NFC intent messages and
how do I eventually get messages?
My guess would be to call enableForegroundDispatch method. Define it like:
procedure enableForegroundDispatch; cddcl;
to call it from Android API
But since I have never done this before, I do not know how to proceed
Edit : Seems I have missed a tag and the OP does not ask for Java code. Leaving this anyway for future reference
Your guess is correct, although it might be possible to define the intents you want to listen for in the AndroidManifest.xml, foreground dispatch really puts your app in the front, giving you the ability to capture all launched NFC intents.
The way it is described in the docs gives you a clue.
I assume you're familiar with the lifecycle of the Android Activities, Intent Dispatching and such.
Structure
Using the following structure, you'd have 4 fields :
private PendingIntent pendingIntent;
private IntentFilter[] mIntentFilters;
private String[][] mTechLists;
private NfcAdapter mNfcAdapter;
In the onCreate you'd get :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
mIntentFilters = new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED)};
mTechLists = new String[][]{new String[]{Ndef.class.getName()},
new String[]{NdefFormatable.class.getName()}};
}
This does not actually enable the Foreground Dispatch yet, it is just the preparation.
The application would receive the Ndef and NdefFormatable technologies
Why do we subscribe for ACTION_NDEF_DISCOVERED ?
The order in which Android tries to handle the intent is as such :
ACTION_NDEF_DISCOVERED
ACTION_TECH_DISCOVERED
ACTION_TAG_DISCOVERED
So we make sure our app is the first to be looked at by Android.
Enable FGD
Put the following line of code in the onResume method :
if (mNfcAdapter != null) {
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, mIntentFilters, mTechLists);
}
Why is this in the onResume? As the docs state : enableForegroundDispatch() must be called from the main thread and only when the activity is in the foreground (calling in onResume() guarantees this)
This should enable your app to receive the intent, of course, when actually running.
If you want to receive intents while not running, you'd have to go to the AndroidManifest.
If you go to Settings->About Phone->Check for updates a check is initiated to see if theres any system updates ready for your phone.
How can I do this action programmatically? Further, I am trying to locate where in the Android source code this happens so I can see it fully and understand it better. Does anyone have any suggestions?
As far as I know, there is no known broadcast, intent or API to do this programmatically.
And it depends on the ROM, and manufacturer.
Sony for example uses a service which, when the wifi is activated, the service checks on Sony's servers for any updates and informs of it.
But when talking about AOSP source, that I do not think happens.
The nearest point of System update is found in packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java
Protip: grep the string "System update" within the res/values directory and work backwords and find out where that string variable identifier is used!
Edit:
Here's an example broadcast receiver:
public class SystemUpdateClass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent){
if (intent.getAction().equals("android.settings.SYSTEM_UPDATE_SETTINGS")){
Toast.makeText(context,
"Yup! Received a system update broadcast",
Toast.LENGTH_SHORT).show();
}
}
}
Here's an example code, from within a activity's onCreate:
SystemUpdateClass sysUpdate = new SystemUpdateClass();
IntentFilter filter = new IntentFilter();
filter.addAction("android.settings.SYSTEM_UPDATE_SETTINGS");
registerReceiver(sysUpdate, filter);
Now, what should happen is your app should receive the broadcast, unless I am mistaken that the broadcast is only for system-signed apps... however the rest is left as an exercise :)
I'm trying to get a BroadcastReceiver invoked when the screen is turned on. In my AndroidManifest.xml I have specified :
<receiver android:name="IntentReceiver">
<intent-filter>
<action android:name="android.intent.action.SCREEN_ON"></action>
</intent-filter>
</receiver>
However it seems the receiver is never invoked (breakpoints don't fire, log statements ignored). I've swapped out SCREEN_ON for BOOT_COMPLETED for a test, and this does get invoked.
This is in a 1.6 (SDK level 4) project.
A Google Code Search revealed this, I downloaded the project and synced it, converted it to work with latest tools, but it too is not able to intercept that event.
http://www.google.com/codesearch/p?hl=en#_8L9bayv7qE/trunk/phxandroid-intent-query/AndroidManifest.xml&q=android.intent.action.SCREEN_ON
Is this perhaps no longer supported?
Previously I have been able to intercept this event successfully with a call to Context.registerReceiver() like so
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// ...
}
}, new IntentFilter(Intent.ACTION_SCREEN_ON));
However this was performed by a long-living Service. Following sage advice from CommonsWare I have elected to try to remove the long-living Service and use different techniques. But I still need to detect the screen off and on events.
Following sage advice from CommonsWare
I have elected to try to remove the
long-living Service and use different
techniques.
Actually, I believe my advice was more of a light blue... :-)
But I still need to detect the screen
off and on events.
There are certain events that Android does not want to start up new processes for, so the device does not get too slow from all sorts of stuff all having to run at once. ACTION_SCREEN_ON is one of those. See this previous question for light blue advice on that topic.
So, you need to ask yourself, "Self, do I really need to get control on those events?". The core Android team would like it if your answer was "no".
This is the best example I've found http://androidexample.com/Screen_Wake_Sleep_Event_Listner_Service_-_Android_Example/index.php?view=article_discription&aid=91&aaid=115
Actullay i was faceing this issue but i resolve it succeessfully
1) start service from your main activity
Intent i = new Intent(MainActivity.this, UpdateService.class);
startService(i);
2) register reciver in service class.
#Override
public void onCreate() {
super.onCreate();
// REGISTER RECEIVER THAT HANDLES SCREEN ON AND SCREEN OFF LOGIC
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReciever();
registerReceiver(mReceiver, filter);
}
3) Done