Android READ_PHONE_STATE Event - java

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;
}
}
}

Related

retry with varying intervals on each time

I am working on a ble-android communication app. I am getting TYPE_GATT_ERROR sometimes when I try to read values from ble device. So I like to retry the scan and reading values each time the TYPE_GATT_ERROR is seen. first time when it happens, I want to start the scan again after 30secs and if that time also if the code reaches TYPE_GATT_ERROR segment, It should start scan again after 1 min and third time if it reaches the error segment, It should rescan with time interval 2mins. How can I do that with the below code segment? The Elseif case with the TYPE_GATT_ERROR condition is where I want to implement the retry algorithm.
private final BroadcastReceiver bleServiceReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent){
String type = intent.getExtras().getString(
BleReceivedService.EXTRA_TYPE);
if (BleReceivedService.TYPE_GATT_CONNECTED.equals(type)){
Log.d(TAG, " MYTAG DashBoard onReceive TYPE_GATT_CONNECTED");
if (BleReceivedService.getGatt() != null){
BleReceivedService.getGatt().discoverServices();
Log.d(TAG, " Connect Device");
stopScan();
}
} else if (BleReceivedService.TYPE_GATT_DISCONNECTED.equals(type)){
Log.d(TAG, " MYTAG Disconnect Device");
Log.d(TAG, " MYTAG DashBoard onReceive TYPE_GATT_DISCONNECTED");
BleReceivedService.getInstance().disconnectDevice();
if(isScanning) {
Log.d("ScanCheck","Scanning after disconnection");
stopScan();
}
} else if (BleReceivedService.TYPE_GATT_ERROR.equals(type)) {
Log.d(TAG, " MYTAG DashBoard onReceive TYPE_GATT_ERROR");
//here i want to call startscan() method in the above described fashion
} else {
//do someting
}
}
};
Please help me with the code to achieve this.
Thanks in advance.

I have played a song when power connected, but it's not stopping when power is disconnected

I want to play a song when the power is connected, and stop the song when the power is disconnected, but this song still plays when the power is disconnected. Please share working code regarding this.
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
MediaPlayer mMediaPlayer = new MediaPlayer();
mMediaPlayer = MediaPlayer.create(context, R.raw.mysong);
if (intent.getAction() == Intent.ACTION_POWER_CONNECTED) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setLooping(true);
mMediaPlayer.start();
}
else if (intent.getAction() == Intent.ACTION_POWER_DISCONNECTED) {
Toast.makeText(context, "POWER DISCONNECTED !!!!!", Toast.LENGTH_SHORT).show();
mMediaPlayer.stop();
}
}
}
This Link will help you.
You have to register Broadcast for android.intent.action.ACTION_POWER_DISCONNECTED.
and than receive on of power disconnect broadcast stop you media player.
https://techcampuz.blogspot.in/2016/07/how-to-detect-when-power-connected-and.html
And your above code for every broadcast message Mediaplayer created new object so that me be problem, user that outside of the receiver method.

Stop app processes on phone call?

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

Destroy foreground notification when the service get killed

I have a foreground service to download some contents form the web.
Unfortunately, due to bug which reported here my service being killed when a receiver received a broadcast within my service but it's notification won't be killed and I saw the following log in my logcat:
I/ActivityManager(449): Killing 11073:my-package-name/u0a102 (adj 0): remove task
Is there anyway to to destroy foreground notification when it's parent service get killed by OS?
Service ending remove the foreground notification.
#Override
public void onDestroy() {
// mycleanup first
stopForeground(true);
super.onDestroy();
}
Use stopForeground:
#Override
public void onDestroy() {
// as the bug seems to exists for android 4.4
if (android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.KITKAT)
{
stopForeground(true);
}
super.onDestroy();
}
or
public void onTaskRemoved (Intent rootIntent)
{
// as the bug seems to exists for android 4.4
if (android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.KITKAT)
{
stopForeground(true);
}
}
Inside the notification check periodically (e.g. Handler) if service is still running using code below:
public static boolean isMyServiceRunning(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (MyService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
And if not just shut down notification.
private static final int DEALY = 10000;
private Handler handler = new Handler();
...
handler.postDelayed(ensureSericeIsRunning, DELAY);
...
private Runnable ensureSericeIsRunning = new Runnable() {
#Override
public void run() {
if (!isMyServiceRunning(getActivity())){
//shut down notification
} else {
handler.postDelayed(ensureSericeIsRunning, DELAY);
}
}
};
use onDestroy(). Even tho the documentation says it is not guaranteed to be called, I have tested multiple times and the only cases it doesn't get called is when the system kills the process, but to that point your notification will be killed to, so it's ok.
You could remove the notification from onStop or onDestroy inside of your service class.
P.S there no guarantee this would work, in api 14 and above the service can still be running even without foreground notification, you could return START_STICKY that will bring back your service even if the system destroyed it, system will restart it.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
use the service onTaskRemoved() method.

BroadcastReceiver for listening mobile data state

I used a Broadcast Receiver for listening the current wifi state.
So it sets the current state to the text (connected, connecting, disabled,...) of a togglebutton (setText).
It works fine!
But now I want to do the same thing with the mobile data state..
So I used TelephonyManager to setup the receiver:
this.registerReceiver(this.DataStateChangedReceiver,
new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED));
Then I copied the code from the wifi receiver and edited it:
private BroadcastReceiver DataStateChangedReceiver
= new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
// TODO Auto-generated method stub
int extraDataState = intent.getIntExtra(TelephonyManager.EXTRA_STATE ,
TelephonyManager.DATA_DISCONNECTED);
switch(extraDataState){
case TelephonyManager.DATA_CONNECTED:
data_toggle.setChecked(true);
break;
case TelephonyManager.DATA_DISCONNECTED:
data_toggle.setChecked(false);
break;
case TelephonyManager.DATA_CONNECTING:
data_toggle.setChecked(true);
break;
case TelephonyManager.DATA_SUSPENDED:
data_toggle.setChecked(true);
break;
}
}
};
The app starts but nothing happened with the toogleButton..
Is TelephonyManager the wrong way to do this? ConnectivityManager?
I want to set an onclicklistener to turn on / off the mobile data.
How to do this is the next question..
In my work I have used a trick with ACTION_SCREEN_ON and _OFF...... So, the trick is in such thing.... you create boolean variable in Receiver.class, and then change it when connection state is changed.... And then in service (or activity), where you get intent do what to do.....
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = false;
}
Intent i = new Intent(context, InternetService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
}

Categories

Resources