Receive unplugging of headphones takes too long - java

I want to pause the MediaPlayer when the user unplugs his headphones. I found out that I can use the "ACTION_AUDIO_BECOMING_NOISY" broadcast , so I tried it out !
Theoretically it works , BUT the time of receiving takes too long. The music is still playing for 3-5 seconds before it really pauses.This wouldnt be acceptable for an user.
How are other devolopers able to pause it in milliseconds ? Are there better Soloutions ?
My BroadcastReceiver which is actually for Notifications :
public class NotificationBroadcast extends BroadcastReceiver {
...
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
Intent iPause = new Intent(context , SongService.class);
iPause.putExtra("com.Hohos.mplay.Services.SongService.MEDIA_ACTION", NOTIFY_EXTRA_PAUSE);
context.startService(iPause);
}
...
}
I also added <uses-permission android:name="android.permission.ACTION_HEADSET_PLUG"/>
, which really didnt any difference
Thanks for your help guys !

To know when the user unplugs his headphones you need to listen the action ACTION_HEADSET_PLUG and check the state extra:
Broadcast Action: Wired Headset plugged in or unplugged.
The intent will have the following extra values:
state - 0 for unplugged, 1 for plugged.
name - Headset type, human
readable string
microphone - 1 if headset has a microphone, 0
otherwise
This is an example:
public class MainActivity extends Activity {
private HeadsetBroadcastReceiver mHeadsetBroadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myReceiver = new HeadsetBroadcastReceiver();
}
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
registerReceiver(mHeadsetBroadcastReceiver, filter);
super.onResume();
}
#Override
protected void onPause() {
unregisterReceiver(mHeadsetBroadcastReceiver);
super.onPause();
}
private class HeadsetBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
if (state == 0) {
//Headset is unplugged
} else if(state == 1) {
//Headset is plugged
}
}
}
}
}

Related

How to update activity every 2 minutes using broadcast receiver in Android?

I am using broadcastreceiver to update the Activity every minute, however, I want to change it to every 2 minutes. How can I achieve that?
Below is the code for my function -
private void startMinuteUpdated() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_TIME_TICK);
minuteUpdateReceiver= new BroadcastReceiver() {
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onReceive(Context context, Intent intent) {
lastUpdatedTimeTextDeparture.setText(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm")));
}
};
registerReceiver(minuteUpdateReceiver, intentFilter);
}
#Override
protected void onResume() {
super.onResume();
startMinuteUpdated();
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(minuteUpdateReceiver);
}
You can alter your current implementation to read the minutes from current time and if its remainder by 2 is 0 then do your stuff, or else return. Doing this will allow you to update when the minutes are in even value (i.e. running every second minute).
if (Calendar.getInstance().get(Calendar.MINUTE) % 2 != 0){
// don't proceed further
return;
}
// update the activity

interface cannot be cast (ClassCastException: AlarmReceiver cannot be cast to AlarmReceiver$OnAlarmOver)

I created a alarm and I hope when alarm is stop can set a String to TextView in MainActivity so I try to use interface but it's get error :
Caused by: java.lang.ClassCastException: AlarmReceiver cannot be cast to AlarmReceiver$OnAlarmOver
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
public AlarmReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
...
OnAlarmOver onAlarmOver = (OnAlarmOver) context; //<--error
onAlarmOver.OnAlarmOverText("Alarm stop");
}
public interface OnAlarmOver {
public void OnAlarmOverText(String overText);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements AlarmReceiver.OnAlarmOver {
...
public void OnAlarmOverText(String overText){
alarm_text.setText(overText);
}
}
My English is very poor, sorry.
You are trying to cast the context to OnAlarmOver. Of course, this is not going to work. I think you want to capture a broadcast emit somewhere else inside of your app.
1) You need to define your broadcast. Then, in your activity, you should register it. For example:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
if(intent.getAction().equals(SearchService.NOTIFICATION)){
}
}
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter(SearchService.NOTIFICATION));
}
Remember to unregister in the pause method
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
2) You need to create an Intent and the send the broadcast like this.
private void publishResults(Search result) {
Intent intent = new Intent(NOTIFICATION);
intent.putExtra(RESULT, result);
sendBroadcast(intent);
success = true;
}
To sum up, I don't know why you want to use an interface (listener) for this if it is is provided by Android. Maybe, you should explain a little more what do you want to do. I hope this answer can help you.

IntentService does broadcast but onReceive doesn't receive broadcast

(NOTE that at the end of this Question I have an EDIT in which I have replaced one method with what the Answer said to do in order to fix the problem of onReceive never getting called and added onDestroy to fix a new problem that cropped up after fixing first problem.)
Here's how I attempted to capture the broadcast data, but onReceive never gets called since Log.w never displays anything:
public class MatchesActivity extends Activity implements DatabaseConnector.DatabaseProcessListener
{
public static String SOME_ACTION = "com.dslomer64.servyhelperton.SOME_ACTION";
public static String STRING_EXTRA_NAME = "match";
#Override protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
LocalBroadcastManager.getInstance(this).registerReceiver
(
new BroadcastReceiver()
{
#Override public void onReceive(Context context, Intent intent)
{
String s = txaMatches.getText().toString() + intent.getStringExtra(STRING_EXTRA_NAME) ;
txaMatches.setText(s);
Log.w("MatchesActivity","`````onReceive <" + s + ">");
}
}, new IntentFilter(SOME_ACTION)
);
...
DatabaseConnector dbc = new DatabaseConnector(getApplicationContext(), assets);
dbc.setDbProcesslistener(this); // set way to know matches has been defined
dbc.findDBMatches();
} // end onCreate
} // end MatchesActivity
Database connector:
public DatabaseConnector(Context _context, AssetManager _assets)
{
mContext = _context;
//This method, called in `MatchesActivity` on button press, does start the service:
public void findDBMatches()
{
Intent i= new Intent(mContext, QueryDB.class);
mContext.startService(i);
}
// Here's the service:
public static class QueryDB extends IntentService
{
public QueryDB() { super(QueryDB.class.getSimpleName()); }
public QueryDB(String name) { super(name); }
//Here's the procedure that does all the work (and it does execute):
#Override protected void onHandleIntent(Intent intent)
{ ...
publishProgress(dicWord); // a String
}
//This does execute but it doesn't send `progress` back to `MatchesActivity`,
//which initiated request for service (note: `publishProgress` is so named
//because `QueryDB` used to be an `AsyncTask` and I just didn't change the name):
protected void publishProgress(String progress)
{
Intent intent = new Intent(MatchesActivity.SOME_ACTION);
intent.putExtra(MatchesActivity.STRING_EXTRA_NAME, progress);
this.sendBroadcast(intent); // THIS LINE IS THE PROBLEM, FIXED BELOW
Log.w("DatabaseConnector", "`````publishProgress <" + progress + ">");
}
}
What connection(s) have I failed to make?
EDIT
This is the CORRECTED method found just above:
protected void publishProgress(String progress)
{
Intent intent = new Intent(MatchesActivity.SOME_ACTION);
intent.putExtra(MatchesActivity.STRING_EXTRA_NAME, progress);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Here is onDestroy in MatchesActivity (which starts the service), necessary to call when service has finished its work:
#Override protected void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
Note that onDestroy refers to a new MatchesIntent variable, defined as:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
{
#Override public void onReceive(Context context, Intent intent)
{
String s = intent.getStringExtra(STRING_EXTRA_NAME) ;
txaMatches.append(s + "\n");
}
};
And onCreate in MatchesActivity got simpler because of defining mMessageReceiver:
#Override protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
LocalBroadcastManager.getInstance(this).registerReceiver
(
mMessageReceiver, new IntentFilter(SOME_ACTION)
);
}
What connection(s) have I failed to make?
In your first block of code, you are using LocalBroadcastManager. In your second block of code, you are not.
Replace:
this.sendBroadcast(intent);
with:
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

BroadcastReceiver fires only once

I have activity where I have EditText for user to enter certain data. After user writes some text and clicks button, he is waiting for a response from BroadcastReceiver. The problem is that everything works for the first time and user receive response but if user doesn't exit activity and clicks the button again, BroadcastReceiver is not firing anymore. If user closes activity and opens it again, BroadcastReceiver is again working but only for the first time.
This is a little bit confusing. Here is my code:
public void onCreate(Bundle savedInstanceState) {
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent in) {
switch (getResultCode()) {
case Activity.RESULT_OK:
mStatus = true;
break;
}
}
};
getActivity().registerReceiver(mReceiver,
new IntentFilter(FLAG));
}
When user clicks button:
Intent in = new Intent(FLAG);
PendingIntent pIn = PendingIntent.getBroadcast(context, 1, in, 0);
SmsManager.getDefault().sendTextMessage("123456789", null, "text", pIn, null);
while(!mStatus){
}
mStatus = false;
Unregister receiver:
public void onPause() {
super.onPause();
getActivity().unregisterReceiver(mReceiver);
}
What do you think? Why it works only when activity is started and button is clicked for the first time?
Try this instead:
public void onPause() {
super.onPause();
// getActivity().unregisterReceiver(mReceiver);
}
public void onDestroy() {
super.onDestroy();
getActivity().unregisterReceiver(mReceiver);
}
Explanation: you should manage the receiver either in onCreate() / onDestroy() or onResume() / onPause() (corresponding lifecycle events).
Edit: make this change also (second line sets flag argument):
Intent in = new Intent(FLAG);
PendingIntent pIn = PendingIntent.getBroadcast(context, 1, in, PendingIntent.FLAG_UPDATE_CURRENT);
SmsManager.getDefault().sendTextMessage("123456789", null, "text", pIn, null);
Not sure if this will fix it because I don't know what the 0 would mean that you were using for the flag value. FLAG_UPDATE_CURRENT seems correct though.
Edit 2:
while(!mStatus){
}
You should never do that!

Go to previous activity from BroadcastReceiver?

I need to close the current activity from a broadcast receiver. I'm not sure how to call finish from it, maybe there is a way to simulate a "Back" key keypress. Any implementation will be fine as long as it does the job.
#Override
public void onReceive(Context context, Intent intent) {
// How can I finish the current activity here?
}
At your broadcast receiver write:
YourCurrentActivityName.this.finish();
Or you can terminate the front activity with this.finish(); so the last open in stuck comes to front.
Update:
Code for first case:
Use of broadcast receiver to terminate activity at back stack:
public class ActivityFirstName extends Activity {
private BroadcastReceiver mFinishReceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// other code
if (mFinishReceiver == null) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.ACTION_TERMINATE");// a string to identify your action
mFinishReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// How can I finish the current activity here?
if ("com.example.ACTION_TERMINATE".equals(intent.getAction())) {
ActivityFirstName.this.finish();
}
}
};
registerReceiver(mFinishReceiver, intentFilter);
}
// other code
}
#Override
protected void onDestroy() {
super.onDestroy();
if (isFinishing()) {
if (mFinishReceiver != null) {
unregisterReceiver(mFinishReceiver);
}
}
}
}
And the front/current running activity, the sender of the broadcast:
public class ActivitySecondName extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
// code code code
final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Perform action on click
terminateBackActivities();
}
});
}
private void terminateBackActivities() {
Intent i = new Intent("com.example.ACTION_TERMINATE"); // the two action strings MUST be same
// i.putExtra(...); // to send extra data
sendBroadcast(i);
}
}
You can simply call this.finish();
Assuming from your comment that the BroadcastReceiver is not an internal class of the activity, here is what you should do: Rather than having the broadcast receiver in a separate class, define it inside your activity like so:
private BroadcastReceiver mFinishReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent){
YourActivity.this.finish();
}
};
Then, you will want to register the receiver in onResume() as such:
#Override
public void onResume(){
super.onResume();
registerReceiver(mFinishReceiver, new IntentFilter(yourIntentAction));
}
You will also want to unregister this receiver in onPause() so you don't leak it:
#Override
public void onPause(){
super.onPause();
unregisterReceiver(mFinishReceiver);
}
Then you can remove the other receiver that had its own separate class and also remove its definition in the manifest. The above example will ensure that you can always call finish() with no issues because the receiver is only registered when the activity is running, as it is internal to the activity's class.
EDIT: Change the methods to onCreate() and onDestroy() rather than onPause() and onDestroy(), according to madlymad's comment.
The ActivityManager class can give you the current foreground activity (even if it's not from your app). The getRunningTasks methods will give you a list of the running tasks, the first element of the list being the most recent launched activity.Unfortunately,this method will just give you an object of type RecentTaskInfo , not the activity itself, so there is no way to call its finish() method,I believe :/
On the other hand, if you want to close the current activity from your app, you can implement a static variable on a personal class that each activiy would set in their onResume() method. This way you will always know what activity is the current one. But I guess it's not what you are looking for.
Edit: The getRunningTasks is just intended for debug purposes, as says the doc..
As suggested by other answers you can simply call finish() on the activity in the broadcast receiver code or you can even trigger a back button press key event yourself.
this.dispatchKeyEvent(new Keyevent(ACTION_DOWN, KEYCODE_BACK));
Not sure about whether this is helpfull to you or not but its help me once and i think thats a same case here so i am answering for you.
Whenever the broadcast receiver get call, you can navigate to any activity by clicking on that broadcast message.
Just like:
#Override
public void onReceive(Context context, Intent intent) {
// My Notification Code
notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
int icon = R.drawable.app_icon;
//System.out.println("The ID Number is: "+Long.parseLong(intent.getData().getSchemeSpecificPart()) );
contentText = intent.getStringExtra("MyMessage");
System.out.println("The Message is: "+intent.getStringExtra("MyMessage"));
CharSequence text = "Your tax amount due period";
CharSequence contentTitle = "Tax Toolbox";
long when = System.currentTimeMillis();
intent = new Intent(context, MenuPageActivity.class); // here i am calling activity
intent.putExtra("sixMonth", "sixMonth");
intent.putExtra("messageSixMonth", contentText);
PendingIntent contentIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification = new Notification(icon,text,when);
long[] vibrate = {0,100,200,300};
notification.vibrate = vibrate; // To vibrate the Device
notification.ledARGB = Color.RED;
notification.ledOffMS = 300;
notification.ledOnMS = 300;
notification.defaults |= Notification.DEFAULT_LIGHTS;
//notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
notificationManager.notify(com.project.TaxToolbox.NotificationConstants.NOTIFICATION_ID_SIX_MONTH, notification);
}
Now, on the onCreate() of that activity you have to identify whether it is call by Notification or not.
As like:
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
System.out.println("The Extra for twoMonth is: "+getIntent().hasExtra("twoMonth"));
System.out.println("The Extra for sixMonth is: "+getIntent().hasExtra("sixMonth"));
System.out.println("The Extra for EveryMonth is: "+getIntent().hasExtra("everyMonth"));
if(getIntent().hasExtra("sixMonth")){
notificationManager.cancel(NotificationConstants.NOTIFICATION_ID_SIX_MONTH);
final AlertDialog alert3 = new AlertDialog.Builder(MenuPageActivity.this).create();
alert3.setTitle("Tax Toolbox");
alert3.setMessage(getIntent().getExtras().getString("messageSixMonth"));
alert3.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alert3.setIcon(R.drawable.app_icon);
alert3.show();
// here you can do anything more or close the activity.
}
Not sure but might be helpfull to you.
Feel free to comments if it help you.
Create a common Activity class and extend this common class from all activities, that way you can have a centralized code. Have a register the broadcast receiver in onStart of the activity and unregister in onStop that way only one activity, the one which is visible will be registered for the broadcast intent.
Sample code:
public class BaseActivity extends Activity {
/*
* (non-Javadoc)
*
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(receiver, new IntentFilter(YOUR_INTENT_FILTER));
}
/*
* (non-Javadoc)
*
* #see android.app.Activity#onStop()
*/
protected void onStop(){
unregisterReceiver(receiver);
}
/*
* (non-Javadoc)
*
* #see android.app.Activity#onStart()
*/
protected void onStart(){
super.onStart();
registerReceiver(receiver, new IntentFilter(YOUR_INTENT_FILTER));
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
/*
* (non-Javadoc)
*
* #see
* android.content.BroadcastReceiver#onReceive(android.content.Context,
* android.content.Intent)
*/
#Override
public void onReceive(Context context, Intent intent) {
onBackPressed();//on back pressed simply calls finish()
}
};
} // End of BaseActivity
// End of File
Try using:
Intent i = new Intent(context,intent.getClass());
Follow the instructions from gezdy on How to get current foreground activity context in android? to ensure you can get a reference to the current activity from anywhere in your application.
From there you can call .finish() to close the current activity.
Place finish(); after u completed all the tasks in onReceive() of BroadcastReceiver class as below:
#Override
public void onReceive(Context context, Intent intent) {
// Do all the tasks onReceive of BroadCast Receiver
finish(); // This finishes the current activity here....
}

Categories

Resources