Reputation: 217
I am trying to get my service to run when there is an outgoing call on my phone. But for some reason my service does not run when this happens. I know the code for the "CallReceiver" executes since I used a toast message to display if that runs. I am able to run the service through my main activity, but this means it will run regardless of whether an outgoing call is made....
Below is my code:
The Receiver:
package com.example.hiworld;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class CallReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, CallService.class));
Toast.makeText(context, "Call Receiver started",
Toast.LENGTH_LONG).show();
Log.d("Calling Someone", "onReceived");
}
}
The Service:
package com.example.hiworld;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;
public class CallService extends IntentService {
public long StartTime=0;
public long EndTime =0;
public long TotalTime = 0;
public long NumFreeMins = 0;
public CallService() {
super("CallService");
}
@Override
protected void onHandleIntent(Intent intent) {
StartTime = (System.currentTimeMillis())/60;
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if(tm.getCallState()==0) //getting the time whenever the phone is off
{
EndTime = (System.currentTimeMillis())/60;
TotalTime = EndTime-StartTime;
NumFreeMins = 300-TotalTime;
//notify user
this.displaymsg();
}
}
public void displaymsg()
{
Toast toast = Toast.makeText(getApplicationContext(), ""+NumFreeMins, Toast.LENGTH_SHORT);
toast.show();
}
}
I have seen some people use the line:
context.startService(new Intent(this, CallService.class));
instead of:
context.startService(new Intent(context, CallService.class));
but the latter does not work for me...
Upvotes: 1
Views: 1486
Reputation: 48871
Try specifying an <intent-filter>
for your IntentService
in the manifest for a specific 'action'. Example...
<service
android:name=".CallService" >
<intent-filter>
<action android:name="com.example.hiworld.intent.DO_SOMETHING" />
</intent-filter>
</service>
Then in the onReceive(...)
method of your BroadcastReceiver
do something like the following...
Intent callReceiverIntent = new Intent("com.example.hiworld.intent.DO_SOMETHING");
// Put the Intent received by the BroadcastReceiver as extras so the
// IntentService can process it...
callReceiverIntent.putExtras(intent);
context.startService(callReceiverIntent);
EDIT:
I built a simple test app based on the code you posted to pasrebin. I kept the code identical for the manifest, receiver and service and simply had to add a default Activity
in order to get it to run.
I can see from monitoring logcat in the DDMS perspective of eclipse that the CallReceiver
successfully receives the NEW_OUTGOING_CALL
Intent
and does, in fact, start the CallService
.
The problem is, however, with attempting to show a Toast
from an IntentService
which causes an exception due to a 'leaked handler' and silently crashes.
The reason behind this is that an IntentService
uses a background thread to carry out its work and trying to show the Toast
(i.e., a UI element) from a non-UI thread won't work as the app has no UI components running. So, regardless of whether you use the local context
variable or getApplicationContext()
, there simply is no UI context with which to associate the Toast
.
The reason why it works when starting the CallService
from an Activity
is obviously because the Activity
provides a UI context that can be used by the Toast
. In short, it generally seems that attempting to use Toast
from an IntentService
isn't a good idea unless the IntentService
is always started by a UI component and even then, having a background thread create UI elements (such as a Toast
) may cause problems.
The only way that this can be made to work with the current model is to change the IntentService
to a Service
. By default, code execution of a Service
is done on the main (UI) thread and it is quite legal for a Service
to show a Toast
regardless of whether there are any of the app's Activities
showing or not. In fact, I modified the code to use a Service
and placed the code from onHandleIntent
in onStartCommand()
and I can see the Toasts
when making an outgoing call.
Upvotes: 1
Reputation: 1498
Try
context.startService(new Intent(context.getApplicationContext(), CallService.class));
Upvotes: 0