I am building an app that starts a service each time a call is being made, the first time I create a call the broadcast receiver starts the service and all is well.
But then the problem: Once I run the dialer again I get the following error in LogCat:
10-30 10:10:38.674: E/StrictMode(171): class com.android.phone.OutgoingCallBroadcaster; instances=2; limit=1
I have tried solving the problem by calling this command at the end of the onReceive:
this.abortBroadcast();
This removes the error, but also stops the service from running again, can anyone help me fix this problem, or is there anyone who has experienced this inconvieniance?
This is the receiver:
public class OutgoingCallReceiver extends BroadcastReceiver {
public OutgoingCallReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
// Extract phone number reformatted by previous receivers
String phoneNumber = getResultData();
if (phoneNumber == null) {
// No reformatted number, use the original
phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
Intent in = new Intent(context, OutgoingCallHandler.class);
context.startService(in);
OutgoingCallHandler.phonenumber = phoneNumber;
}
}
And here are the declarations in the manifest:
<service
android:name=".IncomingCallHandler"
android:label="#string/title_activity_main" >
</service>
<receiver android:name=".OutgoingCallReceiver" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
All the help is very welcom!
Do not call abortBroadcast(), as the NEW_OUTGOING_CALL broadcast is an Ordered Broadcast. It has a final broadcast receiver with some post-processing and clean-up to do.
your context.startService(in); will not start another instance of your service if OutgoingCallHandler is still alive. Add a log message to your onStartCommand to check. And, See if you can avoid saving reference to OutgoingCallHandler.phonenumber = phoneNumber; from your onReceive
Related
I am making an app in which I want to start a service as soon as there is an incoming call. What are the various ways to do this in android?
I know broadcast receiver is one way, but I couldn't find any broadcast intent for incoming phone call.
Use action PHONE_STATE to detect incoming calls..
add this to manifest
<receiver android:name="com.example.YourReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
And your receiver
public class YourReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
// This code will execute when the phone has an incoming call
} else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_IDLE)
|| intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_OFFHOOK)) {
// This code will execute when the call is disconnected
}
}
}
I am trying to start a Service on Android as soon as a certain USB device is plugged in. I have already found this example, which launches an (invisible) activity with an intent-filter, which on the other hand launches the service.
However, this seems to me a little bit hackery and I am trying to do the same with a BroadcastReceiver with the following code:
public class UsbMessageReceiver extends BroadcastReceiver {
public UsbMessageReceiver() {
Log.d("UsbMessageReceiver", "Constructor");
}
#Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
Log.d("UsbMessageReceiver", "onReceive");
throw new UnsupportedOperationException("Not yet implemented");
}
}
And the manifest:
<receiver
android:name=".UsbMessageReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
</receiver>
Edit: If forgot to mention that this approach does not work. I don't get the log message and the Error is not thrown. Is this possible without invoking an Activity?
Using bellow code launch the service in on recieve method
context.startService(new Intent(context.getApplicationContext(), MyService.class));
I want to catch ACTION_SHUTDOWN and BOOT_COMPLETE using BroadcastReceiver.
But it turns out both signals never trigger the BroadcastReceiver (I didn't see any log on logcat).
Here is my source code.
I give the permission on Manifest
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
and I try to register the BroadcastReceiver in both ways
protected void onCreate(Bundle savedInstanceState)
{
registerReceiver(BootReceiver, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
registerReceiver(ShutDownReceiver, new IntentFilter(Intent.ACTION_SHUTDOWN));
}
<receiver android:name=".BootReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
and the source code for BootReceiver and ShutDownReceiver are as
private BroadcastReceiver BootReceiver = new BroadcastReceiver()
{
private String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(ACTION_BOOT)){
//my stuff
Log.d("Power", "Boot Complete");
}
}
};
private BroadcastReceiver ShutDownReceiver = new BroadcastReceiver()
{
private String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_SHUTDOWN)) {
//my stuff
Log.d("Power", "Shutdown Complete");
}
}
};
also, I unregister both BoradcastReceiver in onDestroy
public void onDestroy()
{
unregisterReceiver(BootReceiver);
unregisterReceiver(ShutDownReceiver);
super.onDestroy();
}
Does anyone know what's wrong with my code?
Or anything I miss? Thank you.
I found out why it didn't work.
Since I use a HTC device, the broadcast messages are different from others.
Shut down event broadcasts "com.htc.intent.action.QUICKBOOT_POWEROFF"
Restart(reboot) event broadcasts "android.intent.action.ACTION_SHUTDOWN"
Power on event broadcasts "com.htc.intent.action.QUICKBOOT_POWERON"
In other device, when shutting down the device, it might broadcast "android.intent.action.QUICKBOOT_POWEROFF".
Chances are that your application is not yet added to the "BOOT_COMPLETED" possible receivers list, starting from Android 3.1, in order to get the "BOOT_COMPLETED" action, your application must have been started explicitly by the user, either showing an Activity or another Component, until then your application will not receive the broadcast you are expecting, is important to know that if you "Force Close" the application, it will be missing the broadcasts again, So, try to open an activity and then reboot your device, you will get it...
Hope this Helps!
Regards!
Try this.
<receiver
android:name="packagename.GPSReceiver"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter android:priority="500" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
BOOT_COMPLETED must be registered in the manifest. You cannot register for it via registerReceiver(), because by the time you call registerReceiver(), the boot will have long since occurred.
AFAIK the shutdown broadcast works with registerReceiver(), though in your case it will only be around when your process is running.
My project is simple. It has an activity and a broadcast receiver. From within my app I want to be able to send sms and to receive sms. This works great.
But now I want to pass some data from the view to the receiver. Imagine a simple checkbox, I want to pass its value to the receiver.
So this is the basic life cycle of my app:
Start app
Press Send SMS
Receiver is started with params and sms is send
Receiver gets an sms and stops.
Receiver:
<receiver android:name=".SmsReceiver">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Activity:
Receiver:
I tried to pass a value, but it seems to be ignored. Any ideas?
You cann't just start and stop a BroadcastReceiver at any time you want. BroadcastReceiver is only alive while onReceive() is executing.
To send a broadcast you should use sendBroadcast(this.service) instead of startService(this.service);
Once you change it to sendBroadcast(this.service) you will receive TWO broadcasts (first from your sendBroadcast() and second from SmsManager). This is definitely not what you want because in the first case you will be able to get your checked param but not SmsMessage and vice versa in the second case.
You can just store this checked param in the SharedPreferences and then retrieve it on onReceive()
Use Custom Intent Broadcasting to Achieve Current flow . make changes in your code as:
STEP 1 :
register an Custom Intent with SMS_RECEIVED in Manifest as :
<receiver android:name=".SmsReceiver">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="xx.xxx.xxx.intent.action.SMS_STATUS_ACTION" />
</intent-filter>
</receiver>
STEP 2 :
public class SmsReceiver extends BroadcastReceiver {
public static final String STATUS_INTENT =
"xx.xxx.xxx.intent.action.SMS_STATUS_ACTION";
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
if (arg1.getAction().equals(SmsReceiver.STATUS_INTENT)) {
// get value here sended from Activity
}
else{
// Check for SMS_RECEIVED Action here
}
}
}
STEP 3 :
send value from your Activity as using sendBroadcast :
public static final String STATUS_INTENT =
"xx.xxx.xxx.intent.action.SMS_STATUS_ACTION";
#Override
public void onClick(View v) {
int checked = 0;
if(this.param.isChecked()){
checked = 1;
}
// put value here
Intent intent = new Intent();
intent.putInt("param", checked);
intent.setAction(CUSTOM_INTENT);
sendBroadcast(intent);
}
I want to make an application in which once the application starts, it will show two button(start and stop button) and once the user clicks the start button the call function will be blocked for the time period till the user again start the application and click the stop button to stop this function. any help please its urgent
in short I Will tell I want to block the outgoing call from my phone by using this activity only
please is there any way to do so???
You can block the outgoing call using the setResultData(null) function in the onReceive method of the Broaadcast receiver.
public class BlockOutgoing extends BroadcastReceiver
{
String number;
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("12280", "asdasNumber is-->> " + number);
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
setResultData(null);
Toast.makeText(context, "Outgoing Call Blocked" , 5000).show();
}
}
In the manifest file, you need to register the receiver like this,
<receiver
android:name=".BlockOutgoing"
android:label="#string/app_name" >
<intent-filter android:priority="1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Also define the permission to intercept the outgoing call,
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
Edit-
To unregister a broadcast receiver, follow this link
public class BlockOutgoing extends BroadcastReceiver {
String number;
#SuppressLint("WrongConstant")
#Override
public void onReceive(Context context, Intent intent)
{
// Log.d("12280", "asdasNumber is-->> " + number);
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
setResultData(null);
Toast.makeText(context, "Outgoing Call Blocked" , 5000).show();
}
}
<receiver
android:name=".BlockOutgoing"
android:label="#string/app_name" >
<intent-filter android:priority="1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>