I am using the following code in onPause to check the call interruption in my app
//called inside ONPAUSE i.e. whenever my app is interrupted
ActivityManager activityManager = (ActivityManager)getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
String packageLaunched = runningTasks.get(0).baseActivity.getPackageName();
// see package name of app which interrupted my app
if (!packageLaunched.contains("package.name.of.my.app")) {
// do whatever when any other app interrups, as its on top.
}
The problem is,
packageLaunched used to change when call interrupted my app on previous versions of android.
But on android Lollipop call isn't in any running task :/
How can i track an incoming call from my android app?
Register a BroadCastReciever for a Incoming call intent and do it in onRecieveIntent . Only a workaround though but will do the trick in all cases and all os versions.
This solution works on every version of android, including lollipop
Use this broadcast reciever
class TeleListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
// CALL_STATE_IDLE;
Toast.makeText(getApplicationContext(), "CALL_STATE_IDLE",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// CALL_STATE_OFFHOOK;
Toast.makeText(getApplicationContext(), "CALL_STATE_OFFHOOK",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_RINGING:
// CALL_STATE_RINGING
Toast.makeText(getApplicationContext(), incomingNumber,
Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "CALL_STATE_RINGING",
Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
}
and register it like this in onCreate
TelephonyManager TelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
TelephonyMgr.listen(new TeleListener(), PhoneStateListener.LISTEN_CALL_STATE);
And yes, please dont miss
Cheers! Your problems is solved ;)
Related
When I start my MediaPlayer, other apps that are playing audio don't stop. Same when using MediaRecorder.
I managed to use AudioManager to have some functionality, but much of that class is either deprecated, or for high APIs.
For example, I can register a callback, but I can't unregister it cause the abandonAudioFocus() is deprecated.
Looking at sources, it tells me to use a MediaSession, but that's too complicated for my simple goal of playing a simple recorded audio, I don't want to use all the functionality of every single Android platform.
You can do that with AudioManager
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
// Request audio focus for playback
int result = am.requestAudioFocus(focusChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// other app had stopped playing song now , so u can do u stuff now .
}
Audio focus is assigned in turn to each application that requests it.
This means that if another application requests audio focus, your
application will lose it. You will be notifi ed of the loss of audio
focus through the onAudioFocusChange handler of the Audio Focus Change
Listener you registered when requesting the audio focus
private OnAudioFocusChangeListener focusChangeListener =
new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
AudioManager am =(AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch (focusChange) {
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) :
// Lower the volume while ducking.
mediaPlayer.setVolume(0.2f, 0.2f);
break;
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) :
pause();
break;
case (AudioManager.AUDIOFOCUS_LOSS) :
stop();
ComponentName component =new ComponentName(AudioPlayerActivity.this,MediaControlReceiver.class);
am.unregisterMediaButtonEventReceiver(component);
break;
case (AudioManager.AUDIOFOCUS_GAIN) :
// Return the volume to normal and resume if paused.
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.start();
break;
default: break;
}
}
};
I'm developing an app which detecting BLE signal from specific beacons continuously. The content of the signal will be changed if the batteries of these beacons are going to die. As a result, I can prompt the user that which beacon is going to die and he or she may need to change or recharge its battery.
I put the detection in Service and in general situation it just works perfectly. No matter the app is in foreground or background, the app will send a notification to the user with vibration and sound as long as the app detects abnormal signals. The following is the setting of Notification in my code:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(getResources().getString(R.string.app_name))
.setContentText(getResources().getString(R.string.app_name))
.setAutoCancel(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(contentIntent)
.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
.setSound(sound)
.setVibrate(new long[]{INTERVAL_VIBRATE, INTERVAL_VIBRATE});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
builder.setPriority(Notification.PRIORITY_DEFAULT);
builder.setFullScreenIntent(contentIntent, true);
}
if (!TextUtils.isEmpty(message)) {
builder.setContentText(message);
}
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, builder.build());
Here comes the problem:
When the user is talking on the phone he or she will receive notifications, as well as vibrations. But cannot receive notification sound, I would like to know if there is a way to accomplish this feature.
I finally figure out an alternative solution: use ToneGenerator to play sound.
In this case, when I use only Notification, the sound of the notification disappeared when I'm on phone, even though the vibration still works, I want to find an advanced way to prompt the user that he or she is needed to beware of something.
So, in my service, I add PhoneStateListener to monitor my phone state
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener phoneStateListener = createPhoneStateListener();
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
my createPhoneStateListener() method:
private PhoneStateListener createPhoneStateListener() {
return new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch(state){
case TelephonyManager.CALL_STATE_IDLE :
isUserSpeakingOnPhone = false;
break;
case TelephonyManager.CALL_STATE_RINGING :
isUserSpeakingOnPhone = true;
break;
case TelephonyManager.CALL_STATE_OFFHOOK :
isUserSpeakingOnPhone = true;
break;
}
super.onCallStateChanged(state, incomingNumber);
}
};
}
I use a boolean isUserSpeakingOnPhone to determine if I need to start an IntentService which called PlayToneService to generate tones and play at the same time when I need to push a notification:
if (isUserSpeakingOnPhone) {
Intent playTone = new Intent(this, PlayToneService.class);
startService(playTone);
}
PlayToneService.class:
public class PlayToneService extends IntentService {
public PlayToneService() {
super(PlayToneService.class.getName());
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
// play tone
try {
ToneGenerator toneGenerator= new ToneGenerator(AudioManager.STREAM_SYSTEM, ToneGenerator.MAX_VOLUME);
toneGenerator.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200);
Thread.sleep(200);
toneGenerator.stopTone();
toneGenerator.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Then, when the user is speaking on phone and receives a notification, instead of a notfication sound, he/she will hear the "beep" sound from device's speaker. When the user is not speaking on phone, the notification sound will work as usual.
I have an app which plays audio. The thing is, when I get a call on my phone while I am interacting with the app, the audio continues to play. This becomes a problem because the audio makes it hard to understand what the person is saying. Is there any method that gets called when the user is talking on a call? That way I can mute my audio there. I have thoroughly researched the activity life cycle, but cannot find anything that will help me with this issue. I really appreciate all of your expert advice.
I have tried to put this code into my BaseActivity which gets extended by all other activities:
PhoneStateListener phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING) {
//Incoming call: Pause music
TwentySeconds.stopTimer();
Intent i = new Intent(BaseActivity.this, FinishedBeforeTimer.class);
startActivity(i);
Toast.makeText(BaseActivity.this, "INCOMING CALL", Toast.LENGTH_SHORT).show();
} else if(state == TelephonyManager.CALL_STATE_IDLE) {
//Not in call: Play music
} else if(state == TelephonyManager.CALL_STATE_OFFHOOK) {
//A call is dialing, active or on hold
TwentySeconds.stopTimer();
Intent i = new Intent(BaseActivity.this, FinishedBeforeTimer.class);
startActivity(i);
Toast.makeText(BaseActivity.this, "DIALING", Toast.LENGTH_SHORT).show();
}
But then the strangest thing happens. When I call the my phone, the phone I am calling with says that I can't call my phone. I am confused as to what to do now, I really appreciate your time.
Thanks,
Rich
I am working on a messaging app, it sends user notification when he is on a different activtyon my app or is on another app but if the user is on MessagingActivity.java it just updates the chat history and does not send any notifications which is perfectly fine, but the problem arises when the user is on MessagingActivity.java meanwhile an email or something else happen user leaves the MessagingActivity.java open and checks that app if in the meantime a message comes user does not receive any notifications
public void parseRequest(Bundle extras) {
if (extras.containsKey("for") && extras.containsKey("recipientID")) {
if (Integer.parseInt(extras.getString("recipientID")) == M.getID(this)) {
switch (extras.getString("for")) {
case "chat":
if (isRunning("MessagingActivity")) {
Intent intent = new Intent("update_messages_list");
intent.putExtra("data", extras);
sendBroadcast(intent);
} else {
Intent resultIntent = new Intent(this, MessagingActivity.class);
resultIntent.putExtra("conversationID", Integer.parseInt(extras.getString("conversationID")));
resultIntent.putExtra("recipientID", Integer.parseInt(extras.getString("ownerID")));
M.showNotification(getApplicationContext(), resultIntent,
extras.getString("ownerUsername"),
extras.getString("message"),
Integer.parseInt(extras.getString("conversationID")));
}
Let me know how you are checking that your MessageActivity is Running i.e. functioning of isRunning("MessagingActivity") method. If you are setting any global boolean variable for checking this and making isRunning value false in onDestroy() method of that activity then, according to life cycle of Activity it is not called until your activity is finished i.e. in your case user just switching from MessageActivity to Mail .
I am by no means an expert, but you could just set a boolean variable by overriding the Activity's onPause() and onResume() events.
Simply set msgActivityActive to true in onResume(), false in onPause(), and change your call to:
if (isRunning("MessagingActivity") && msgActivityActive)
Can i use loops in READ_PHONE_STATE event?
I want to work loop when phone started ringing to end ringing.
also same the case of user start calling to disconnect the call.
This is my broadcast receiver class
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
while (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
//wate for user shaking the phone
//call ansered
}
while (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
//do something while phone answered
//I want to work something during the calling time
}
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE) {
//do some
}
}
}
You've already done all the necessary research, it's just probably not 'looping' that you want to do.
What you need is to start something when the phone rings, and stops when it stops ringing. Same for in-call.
To handle events while the phone is ringing, start doing something on CALL_STATE_RINGING, then wait for either CALL_STATE_OFFHOOK or CALL_STATE_IDLE to know when ringing has stopped.
Same for while the user is making a call: start something when your receiver receives CALL_STATE_OFFHOOK and stop when it receives CALL_STATE_IDLE.
I would have your BroadcastReceiver send a message (or call a function) in your UI thread to do what you need to do, then notify when call state has changed.
You don't need to be looping during those intervals. You just want to start/stop doing something at the right time. You can always put some backup security (eg: if phone rang and nothing happened for 3 mins, I stop doing something) to make sure you won't keep running things when you don't want to be.
You can detect when an incoming call is picked/dropped, and when an outgoing call is started/stopped so implement your "looping" logic in the associated callbacks. I've included comments in the code below:
public abstract class PhoneCallReceiver extends BroadcastReceiver {
static CallStartEndDetector listener;
#Override
public void onReceive(Context context, Intent intent) {
savedContext = context;
if(listener == null){
listener = new CallStartEndDetector();
}
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
public class CallStartEndDetector extends PhoneStateListener {
int lastState = TelephonyManager.CALL_STATE_IDLE;
boolean isIncoming;
public PhonecallStartEndDetector() {}
//Incoming call- IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when hung up
//Outgoing call- from IDLE to OFFHOOK when dialed out, to IDLE when hunged up
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
if(lastState == state){
//No change
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
//incoming call started
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing down on them
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
//outgoing call started
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//End of call(Idle). The type depends on the previous state(s)
if(lastState == TelephonyManager.CALL_STATE_RINGING){
// missed call
}
else if(isIncoming){
//incoming call ended
}
else{
//outgoing call ended
}
break;
}
lastState = state;
}
}
}