Killing and recreating an activity in a service in android development - android

I am newbie in android development. So I need help .
i would like to display an activity when phone state is ringing, and kill this activity when state is idle or offhook.
So I built a class extends Broadcastreceiver. I call myphonestatelistener class extends PhoneStateListener . Also i create an activity named ringingactivity.
Here is my code (MyPhoneStateListener):
public void onCallStateChanged(int state,String incomingNumber){
switch(state)
{
case TelephonyManager.CALL_STATE_IDLE:
Log.d("DEBUG", "IDLE");
Intent killIntentidle = new Intent();
killIntentidle.setAction("RingingOver") ;
ctx.sendBroadcast(killIntentidle);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("DEBUG", "OFFHOOK");
Intent killIntent = new Intent();
killIntent.setAction("RingingOver") ;
ctx.sendBroadcast(killIntent);
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("DEBUG", "RINGING");
Intent dialogIntent = new Intent(ctx , RingingActivity.class) ;
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(dialogIntent);
break;
}
}
In my tests, i call emulator from telnet and it succesfully display activity when it is ringing. When i accept or decline call, activity is finished . But when i call emulator again, activity could not be recreated again. I cant see it on the screen. What am i doing wrong?
Here is my activity code :
public class RingingActivity extends Activity {
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.ringing_activity);
IntentFilter filter = new IntentFilter();
filter.addAction("RingingOver");
registerReceiver(receiver, filter);
//registerReceiver(receiver,filter) ;
}
public void finish() {
super.finish();
};
}
Thanks for your help!

I suspect the issue is in your MyPhoneStateListener code. The other code look O.K to me.
Some how your PhoneStateListener is not alive next time. Are you able to see "RINGING" logs for second time?

I am not sure as why you need to call Garbage Collector. Please try to fix the root cause as why, activity is not created; sometimes. First analyze the issue by putting logs in your MyPhoneStateListener and RingingActivity. In MyPhoneStateListener, do print the state of RingingActivity activity, before taking any action (Start/kill activity).

Thank you very much for your reply Munish Katoch. I have a solution but not sure if i find the right solution . when I use Garbage Collecter , activity could be seen in screen in each calling.
Here is my code :
public class MyPhoneStateListener extends PhoneStateListener {
Context ctx ;
private boolean iscalling ;
MyPhoneStateListener(Context ctx)
{
this.ctx = ctx ;
}
public void onCallStateChanged(int state,String incomingNumber){
switch(state)
{
case TelephonyManager.CALL_STATE_IDLE:
Log.d("DEBUG", "IDLE");
if(iscalling == true)
{
Intent killIntentidle = new Intent();
killIntentidle.setAction("RingingOver") ;
ctx.sendBroadcast(killIntentidle);
System.gc() ;
iscalling = false ;
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("DEBUG", "OFFHOOK");
if(iscalling == true)
{
Intent killIntent = new Intent();
killIntent.setAction("RingingOver") ;
ctx.sendBroadcast(killIntent);
System.gc() ;
iscalling = false ;
}
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("DEBUG", "RINGING");
iscalling = true ;
Intent dialogIntent = new Intent(ctx , RingingActivity.class) ;
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(dialogIntent);
System.gc() ;
break;
}
}
}

Related

How to pause the service while getting a incoming call and resume the service after call has ended?

My app is has a simple service, i need to pause that service when user makes or receive a call and service has to resume after call has ended.
Here is my Main Activity looks like:-
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(getApplicationContext(), MyService.class);
startService(intent);
TelephonyManager TelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
TelephonyMgr.listen(new TeleListener(),
PhoneStateListener.LISTEN_CALL_STATE);
}
class TeleListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Toast.makeText(getApplicationContext(), "CALL_STATE_IDLE",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Toast.makeText(getApplicationContext(), "CALL_STATE_OFFHOOK",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_RINGING:
Toast.makeText(getApplicationContext(), incomingNumber,
Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "CALL_STATE_RINGING",
Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
}}
Here is my Service class file:-
public class MyService extends Service {
private static final String TAG = "MyService";
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
if (isRunning) {
Log.i(TAG, "Service running");
}
}
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}}
From the TeleListener class in MainActivity i'm able to fetch the phone state. My problem is when the TelephonyManager is equal to CALL_STATE_OFFHOOK i need to pause the MyService and when the TelephonyManager is equal to CALL_STATE_IDLE i need to resume the MyService
you need to use onCallStateChanged method.
put this lines in your onCreate() method,it will initialize object of TelephonyManager and will setup listener for you.
TelephonyManager tManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
ListenToPhoneState listener = new ListenToPhoneState()
tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
class definition of innerclass ListenToPhoneState will be looking like this,
private class ListenToPhoneState extends PhoneStateListener {
boolean callEnded=false;
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
UTILS.Log_e("State changed: " , state+"Idle");
if(callEnded)
{
//you will be here at **STEP 4**
//you should stop service again over here
}
else
{
//you will be here at **STEP 1**
//stop your service over here,
//i.e. stopService (new Intent(`your_context`,`CallService.class`));
//NOTE: `your_context` with appropriate context and `CallService.class` with appropriate class name of your service which you want to stop.
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
UTILS.Log_e("State changed: " , state+"Offhook");
//you will be here at **STEP 3**
// you will be here when you cut call
callEnded=true;
break;
case TelephonyManager.CALL_STATE_RINGING:
UTILS.Log_e("State changed: " , state+"Ringing");
//you will be here at **STEP 2**
break;
default:
break;
}
}
}
Explaination: While the call,your listener will go through following states,
Step 1: TelephonyManager.CALL_STATE_IDLE
initially your call state will be idle that is why the variable callEnded will have the value false.
Step 2: TelephonyManager.CALL_STATE_RINGING
now you are waiting for the receiver person to receive your call
Step 3: TelephonyManager.CALL_STATE_OFFHOOK
you cut the call
Step 4: TelephonyManager.CALL_STATE_IDLE
idle again
NOTE: If you don't want to know when the call ends and what should be done after ending the call then just remove callEnded variable and stop the service whenever you enter in the block of TelephonyManager.CALL_STATE_IDLE
I hope it will be helpful !!
You cannot pause or resume a service, you can start your service again when call ends. Inside PhoneStateListener's TelephonyManager.CALL_STATE_OFFHOOK constant, start your service again! Using different states of PhoneStateListener as mentioned by #Tijo, you can decide when to start or stop your service.

My Broadcastreceiver seem to detect that a call ended, still doesn't do that it should do. Does anybody see the flaws in my code?

I would like to make two calls in a row in an android app. Upon clicking button the app calls the first number. I created the broadcastreceiver below, that detects when the first call ends. It should write out that "First call ended" and then call the second number. It does not seem working. Can anybody spot the mistake in my code?
public class MainActivity extends AppCompatActivity {
public void calling(String phone) {
Intent callIntent = new Intent(Intent.ACTION_CALL)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setData(Uri.parse("tel:" + phone));
callIntent.putExtra("com.android.phone.extra.slot", 1);
startActivity(callIntent);
Intent intent = new Intent(this, CallReciever.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 234324243 , intent, 0);
startActivity(callIntent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button) this.findViewById(R.id.CallButton);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
calling("+36309577686");
}
});
}
public class CallReciever extends BroadcastReceiver {
private Context mContext;
private CustomPhoneStateListener mPhoneListener;
private String incoming_nr;
private int prev_state;
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
if (mPhoneListener == null) {
mPhoneListener = new CustomPhoneStateListener();
// TelephonyManager object
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// Register our listener with TelephonyManager
telephony.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
/* Custom PhoneStateListener */
class CustomPhoneStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (!TextUtils.isEmpty(incomingNumber)) {
incoming_nr = incomingNumber;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
prev_state = state;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
prev_state = state;
break;
case TelephonyManager.CALL_STATE_IDLE:
if ((prev_state == TelephonyManager.CALL_STATE_OFFHOOK)) {
// A call has now ended
//it writes out the call end, but does not call. why?
Toast.makeText(mContext, "Call End", Toast.LENGTH_SHORT).show();
calling("+36303853440");
prev_state = state;
}
else if ((prev_state == TelephonyManager.CALL_STATE_RINGING)) {
// Rejected or Missed call
Toast.makeText(mContext, "Rejected Call", Toast.LENGTH_SHORT).show();
prev_state = state;
}
break;
}
}
}
}
}
You are not registering the CallReciever anywhere. Try this
Button b = (Button) this.findViewById(R.id.CallButton);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
calling("+36309577686");
registerReceiver(new CallReceiver());
}
});
Then unregister the receiver on broadcast is received

How to get the call end/ hanged event?

I have used TelephonyManager.CALL_STATE_OFFHOOK but unfortunately it gets called every time I touch the call button, i.e before the call is actually made.
my code:
public void onReceive(Context context, Intent intent) {
this.context = context;
listener = new CallStateListener();
if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")){
Log.e("Aditya", "Broadcast listner");
//Currently no use
}
TelephonyManager tm = (TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE);
tm.listen(listener,PhoneStateListener.LISTEN_CALL_STATE);
}
public class CallStateListener extends PhoneStateListener {
int lastState = TelephonyManager.CALL_STATE_IDLE;
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// called when someone is ringing to this phone
Toast.makeText(context,"Pioneer Contacts+ Updated",Toast.LENGTH_LONG).show();
Log.e("Aditya", "ringing");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Toast.makeText(context,"Pioneer Contacts+ Updated",Toast.LENGTH_LONG).show();
Log.e("Aditya", "offhook");
break;
}
}
}
The Log Log.e("Aditya", "offhook"); gets printed before the call gets connected. I want to appear it after the call is disconnected.

changing activities on end of a phone call

In the app that I'm making it requires a change in activity on the end of a phone call. The code I'm using isn't working like the way I want it:
protected class EndCallListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber){
switch(state){
case TelephonyManager.CALL_STATE_OFFHOOK:
Intent intent = new Intent(MainActivity.this, Password.class);
startActivity(intent);
break;
default:
}
super.onCallStateChanged(state, incomingNumber);
}
}
Any ideas?

Start activity

when i tryed to start activity when phone stops ringing and it force closes all the time.
so here's my broadcast reciever
public class Incoming extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
MyPhoneStateListener phoneListener=new MyPhoneStateListener();
TelephonyManager telephony = (TelephonyManager)
arg0.getSystemService(Context.TELEPHONY_SERVICE);
phoneListener.context = arg0;
telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
}
}
And this should start activity
public class MyPhoneStateListener extends PhoneStateListener {
int prevstate;
public void onCallStateChanged(int state,String incomingNumber){
if(prevstate==TelephonyManager.CALL_STATE_OFFHOOK && state == TelephonyManager.CALL_STATE_IDLE){
Log.i("PARm","Here the activity should start");
}
else if(prevstate==TelephonyManager.CALL_STATE_RINGING && state == TelephonyManager.CALL_STATE_IDLE){
Log.i("PARM","Here the activity should start");
}
switch(state){
case TelephonyManager.CALL_STATE_IDLE:
Log.d("DECallNoteActivity.get getContext();BUG", "IDLE");
prevstate = state;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("DEBUG", "OFFHOOK");
prevstate = state;
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("DEBUG", "RINGING");
prevstate = state;
break;
}
}
}
i would be pleased if you could tell me how to get context in this case to start Activity or another way how to start it.
Thank you.
The broadcast receiver's context is only valid for the duration of the onReceive call: you can't save it and reuse it later. If you need to start an Activity this way what you will need to so is start a Service from the BroadcastReceiver's onReceive method, and have that service create the phone state listener and launch the required Activity: once it has launched the Activity it can stop itself.

Categories

Resources