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);
}
Related
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
I am trying to listen to a very specific SMS sent from a particular sender containing a particular keyword. For that, I have created a BroadcastReciever which binds to android.provider.Telephony.SMS_RECEIVED through manifest.
If I find that particular sender sending SMS containing that keyword, I need to send the SMS from my application. I have done that in my application through onRecieve() function.
The problem is that I want to listen to SMS_SENT and SMS_DELIVERED events to know that if sms was successfully sent/delivered or not. For that , I am registering these receivers through
context.registerReceiver(smsSentReciever, new IntentFilter(Consts.SENT));
context.registerReceiver(smsDeliveredReciver, new IntentFilter(Consts.DELIVERED));
Though, I have instantiated a seperate AsyncTask from the onRecieve method to do this job, but still I am getting the error below
BroadcastReceiver components are not allowed to register to receive intents
Should I use IntentService instead of AsyncTask from the onRecieve?
or
Should I instantiate an IntentService from AsyncTask executed in onRecieve?
Just register your BroadcastReceiver in your manifest to handle all three Intents, and deal with them separately as they are received.
In AndroidManifest.xml:
<receiver android:name=".YourBroadcastReceiver">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
<intent-filter>
<action android:name="com.mycompany.myapp.SMS_SENT" />
<action android:name="com.mycompany.myapp.SMS_DELIVERED" />
</intent-filter>
</receiver>
In YourBroadcastReceiver.java:
public class YourBroadcastReceiver extends BroadcastReceiver
{
public static final String ACTION_SMS_RECEIVED =
"android.provider.Telephony.SMS_RECEIVED";
public static final String ACTION_SMS_SENT = "com.mycompany.myapp.SMS_SENT";
public static final String ACTION_SMS_DELIVERED = "com.mycompany.myapp.SMS_DELIVERED";
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equals(ACTION_SMS_RECEIVED))
{
}
// etc...
}
}
Note: The SMS_RECEIVED priority is set to 999 so my app can handle the message before other apps, e.g., the platform SMS/MMS app.
I'm trying to recognize incoming calls in thru a broadcast receiver. I'm UNABLE to do so! Infact, I'm unable to 'trigger' the broadcast!
Here's my code:
activate.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(getApplicationContext(),"Clicked",1).show();
final String BROADCAST_ACTION_NAME = ".BroadcastMM";
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION_NAME);
sendBroadcast(intent);
}
}
I dunno if this 'sendBroadcast' is ever triggered! In my Broadcast Receiver file:
public void onReceive(Context context, Intent intent)
{
if(intent.getAction()=="android.intent.action.PHONE_STATE"){
Toast.makeText(c,"BroadCast fired!",1).show();}
Bundle extras = intent.getExtras();
String state = extras.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
Toast.makeText(context, "Ringing", 1).show();
}
}
My manifest file:
<receiver android:name=".BroadcastMM" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" >
</action>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Is there some logic I'm missing? I'm very new to Android, so please help me out.
intent.getAction()=="android.intent.action.PHONE_STATE"
should be
TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent.getAction());
Since this is how you compare Strings (with equals()).
Also, the code you use to broadcast, should never broadcast - there is no ".BroadcastMM" action. Try making an explicit one instead:
Intent intent = new Intent(v.getContext(),BroadcastMM.class);
sendBroadcast(intent);
It is also likely that you can't broadcast android.intent.action.PHONE_STATE, so your if won't be executed if you make an explicit Intent.
If you really want to check that your BroadcastReceiver is working, put printouts/Toasts outside all ifs. Then once you establish that the BroadcastReceiver responds, do your check. Keep in mind though, that since you only listen for one Intent-Filter, the if checking if the Intent is a PHONE_STATE Intent is a bit redundant.
I am trying to develop an android app, in which I want to sent a message from the phone while making call.
The destination number is taken from the application database.
I have completed till that part, but I cant access the broadcast receiver in my activity:
public class PARENT_CALLActivity extends Activity
{
/** Called when the activity is first created. */
String PARENT=null;
EditText edparent;
Button submit;
String parent_number;
public static final String BROADCAST = "sha.pcall.android.action.broadcast";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
edparent=(EditText)findViewById(R.id.editText1);
submit=(Button)findViewById(R.id.btnsubmit);
submit.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
PARENT=edparent.getText().toString();
MyDabasehandler db=new MyDabasehandler(getApplicationContext());
if(db.getContact().equals(null))
{
db.addContact(new Contacts(PARENT));
}
else
{
db.editContact();
}
Intent intent = new Intent(getApplicationContext(),LocationUpdateReceiver.class);
sendBroadcast(intent);
finish();
}
});
}
public class LocationUpdateReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String outgoing_number=intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, outgoing_number, Toast.LENGTH_LONG).show();
}
}
}
If you are creating a separate class by extending Broadcast receiver I suggest you do it in a separate Class file. If you only want to receive broadcasts as long as the activity is open create a private Broadcast receiver variable. like in this question:
Where to register a BroadcastReceiver (Activity lifecycle fun)
In latter case you can register the broadcast receiver variable with this method called registerreceiver.
Here is the link
It all actually depends on the requirements. If you want to receive broadcasts even if your app is closed (or the activity is not in the foreground), you need to register your broadcast receiver in the manifest file like this:
<receiver
android:name="com.example.myapp.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.myapp" />
</intent-filter>
</receiver>
This is an example of google cloud message broadcast receiver. You also need to add intent filter, to specify which type of broadcast you want to receiver. In the above example the broadcast receiver can receive (see the intent-filter tag) two intents with actions:
"com.google.android.c2dm.intent.RECEIVE"
and
"com.google.android.c2dm.intent.REGISTRATION"
After you are done with this you can accomplish your tasks in the overridden onReceive() method of broadcast receiver.
Hope this helps.
I am working in Android 2.1, and I want to detect when the headset is plugged in/taken out. I'm pretty new to android.
I think the way to do it is using a Broadcast receiver. I sublcassed this, and I also put the following in my AndroidManifest.xml. But do you have to register the receiver somehwere else, like in the activity? I'm aware there are lots of threads on this, but I don't really understand what they're talking about. Also, what's the difference between registering in AndroidManifest.xml versus registering dynamically in your activity?
<receiver android:enabled="true" android:name="AudioJackReceiver" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" >
</action>
</intent-filter>
</receiver>
And this was the implementation of the class (plus imports)
public class AudioJackReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.w("DEBUG", "headset state received");
}
}
I was just trying to see if it works, but nothing shows up when I unplug/plug in the headset while running the application.
EDIT: the documentation doesn't say this, but is it possible that this one won't work if registered in the manifest? I was able to get it to respond when I registered the receiver in one of my applications (or do you have to do that anyway?)
Just complementing Greg`s answer, here is the code that you need divided in two parts
Register the Service in the first Activity (here its called MainActivity.java).
Switch over the result of the ACTION_HEADSET_PLUG action in the BroadCastReceiver.
Here it goes:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private MusicIntentReceiver myReceiver;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myReceiver = new MusicIntentReceiver();
}
#Override public void onResume() {
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
registerReceiver(myReceiver, filter);
super.onResume();
}
private class MusicIntentReceiver extends BroadcastReceiver {
#Override public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
Log.d(TAG, "Headset is unplugged");
break;
case 1:
Log.d(TAG, "Headset is plugged");
break;
default:
Log.d(TAG, "I have no idea what the headset state is");
}
}
}
}
Here are two sites that may help explain it in more detail:
http://www.grokkingandroid.com/android-tutorial-broadcastreceiver/
http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html
You have to define your intent; otherwise it won't access the system function. The broadcast receiver; will alert your application of changes that you'd like to listen for.
Every receiver needs to be subclassed; it must include a onReceive(). To implement the onReceive() you'll need to create a method that will include two items: Context & Intent.
More then likely a service would be ideal; but you'll create a service and define your context through it. In the context; you'll define your intent.
An example:
context.startService
(new Intent(context, YourService.class));
Very basic example. However; your particular goal is to utilize a system-wide broadcast. You want your application to be notified of Intent.ACTION_HEADSET_PLUG.
How to subscribe through manifest:
<receiver
android:name="AudioJackReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
Or you can simply define through your application; but. Your particular request; will require user permissions if you intend to detect Bluetooth MODIFY_AUDIO_SETTINGS.
You need to enable the broadcast receiver and set the exported attribute to true:
<receiver
android:name="AudioJackReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>