I have "ComposeActivity" which calls the "SendSMS" method after onClick, which than calls metod in SMS class. I had also registered two BroadcastReceiver: SmsDeliveredReceiver and SmsSentReceiver, similar to: https://stackoverflow.com/a/17164931/1888738. How can I inform ComposeActivity, that sms was succesfullly sent, and that activity can clean some EditText's, and maybe show crouton with information that sms was sent or not(and why)? My codes: http://pastebin.com/LNRuSeBu
If you have receivers to handle when the SMS messages are sent or not sent. You could modify the onReceive of both of the receivers to send and intent to the ComposeActivity by creating an intent and calling intent.setComponent to specify where the intent should go. with some data that tells the ComposeActivity the result of trying to send the message.
Update:
public void onReceive(Context context, Intent arg1) {
Intent i = new Intent(action);
i.setComponent(new ComponentName("com.mypackage.compose","ComposeActivity"));
switch (getResultCode()) {
case Activity.RESULT_OK:
Log.d(getClass().getSimpleName(), "SMS delivered");
intent.setAction("com.mypackage.compose.SMS_SENT"); // String you define to match the intent-filter of ComposeActivity.
break;
case Activity.RESULT_CANCELED:
Log.d(getClass().getSimpleName(), "SMS not delivered");
intent.setAction("com.mypackage.compose.SMS_FAILED"); // String you define to match the intent-filter of ComposeActivity.
break;
}
startActivity(intent); // you may not necessarily have to call startActivity but call whatever method you need to to deliver the intent.
}
At that point it should just be matter of addind an intent-filter and a receiver to your compose activity either via the manifest or programatically. Your call. The strings I used were made up but you could pick an exiting intent action string or declare strings that you use in the intent filter. Again up to you. May also be helpful to look at questions about sending explicit intents to components like Android explicit intent with target component
or looking at the android docs.
Ok, after 5 hours of trying, I've already solved this:
in BroadcastReceiver in onReceive:
Intent intent = new Intent();
intent.setAction("SOMEACTION");
context.sendBroadcast(intent);
in Activity:
public BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("SOMEACTION")) {
Log.d(TAG, "Sent");
}
}
};
and in onCreate Activity I registered BroadcastReceiver:
registerReceiver(receiver, new IntentFilter("SOMEACTION"));
Thats all...
Related
For instance some example here, a phone running 2 or more apps, calling onReceive().
Has android some kind of task order to run all thouse #Overrides by ordered sequence? Probably yes, then in which order, app importance?
App1 & App2:
App1:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
App2:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
deleteMessageFromInbox(message); // or just something that can conflict other Instance
}
};
You can define the order that intents are handled using the android:priority attribute of BroadcastReceivers. When an intent can be handled by multiple receivers, Android generates an ordered list (based on the priority of each receiver) and delivers the intent sequentially.
So in your case, when you register the receivers (via registerReceiver(BroadcastReceiver receiver, IntentFilter filter), all you have to do is assign a higher priority (via a call to setPriority(int priority)) to the intent filter in App1 than to the filter in App2 to make sure that App1 receives the intent before App2.
There is also an old article in the Android developers blog that gives you examples about how to implement this mechanism efficiently.
From the examples this looked straightforward. Maybe you can show me what I did wrong. I can't get an activity to receive a broadcast sent from a local service.
I have Activity1 that start Service1:
startService(new Intent(Activity1.this, Service1.class));
Activity1 then starts Activity2:
startActivity(new Intent(Activity1.this, Activity2.class));
Service1, a local service, listens for downloads:
protected final BroadcastReceiver service2DownloadBroadcastReceiver = new BroadcastReceiver()
{
public void onReceive(final Context context, final Intent intent)
{
...
broadcastDownloadFinished(Uri.fromFile(downloadedFile));
The broadcast receiver of Service1 then broadcasts its own message:
protected Intent broadcastDownloadFinished(final Uri uri)
{
final Intent intent = new Intent(ACTION_DOWNLOAD_FINISHED).setData(checkNotNull(uri));
sendBroadcast(intent);
Activity2, which is in the foreground at the time, listens for the ACTION_DOWNLOAD_FINISHED intent using its own broadcast receiver:
private final BroadcastReceiver activity2DownloadBroadcastReceiver = new BroadcastReceiver()
{
public void onReceive(final Context context, final Intent intent)
{
Log.i(Activity2.class.getSimpleName(), "Received download event: " + intent.getAction() + " " + intent.getData());
Activity2 of course registers the receiver:
protected void onResume()
{
super.onResume();
final IntentFilter downloadIntentFilter = new IntentFilter();
downloadIntentFilter.addAction(ACTION_DOWNLOAD_FINISHED);
registerReceiver(activity2DownloadBroadcastReceiver, downloadIntentFilter);
In case it matters, ACTION_DOWNLOAD_FINISHED is something like "com.example.intent.action.DOWNLOAD_FINISHED".
Service1 receives the download manager event in its receiver and apparently broadcasts its own custom event, but Activity2 never seems to receive it. What did I do wrong? Is it a problem to broadcast an intent in the middle of processing another one? (I wouldn't think so---this is asynchronous, right?)
Update: Just to make sure there is no problem sending a broadcast in the middle of receiving a broadcast, I changed my broadcast code to actually perform the broadcast three seconds later on the main thread:
Log.i(getClass().getSimpleName(), "...ready to broadcast");
final Intent intent = new Intent(ACTION_DOWNLOAD_FINISHED).setData(checkNotNull(uri));
mainThreadHandler.postDelayed(new Runnable()
{
public void run()
{
Log.i(getClass().getSimpleName(), "...broadcasting");
sendBroadcast(intent);
Log.i(getClass().getSimpleName(), "...broadcasted");
}
}, 3000);
Log.i(getClass().getSimpleName(), "...scheduled to broadcast");
As expected, the log says:
...ready to broadcast
...scheduled to broadcast
...broadcasting
...broadcasted
Yet nothing is received in the activity. Please help.
Eureka! I found it! The problem is that I supplied a data URI in my broadcast intent. The Android intent matching rules get a little complicated. If you supply a data URI, then your intent filter must specify a matching MIME type.
Unfortunately, although the Android documentation says that the data type can be inferred from the data URI, apparently Android doesn't know that a file://.../example.jpg is an image. So this doesn't work:
intentFilter.addDataType("image/*");
However, instead of specifying a type, I can specify a scheme that I accept:
intentFilter.addDataScheme("file");
That works! It's a little rough---and a little artificial to restrict my broadcasts to file: URIs, but as that's all I'm using for the moment, it works.
Note that apparently I could manually specify the MIME type in the intent when I broadcast it, but that's too much trouble for now, as I'm downloading images from Picasa so I already know that they are images (and don't care the specific MIME type). And if it gets too much trouble, I could ditch the whole setData() thing altogether and set an extra---but of course I want to do things the Right Way.
have you included your receiver in your activity's manifest?
<receiver
android:name=".YourReceiver">
<intent-filter>
<action
android:name="intent_name"></action>
</intent-filter>
</receiver>
I have an activity for display new sms and SmsReceiver (extends BroadcastReceiver) to receive incoming sms. After receive sms, what is the best practice to update the UI?
Well if you have your own activity it is obious that you want you activity to be shown after the user receive a sms. Then in your receiver , onReceive method you can do this
startActivity(new Intent(context,MyActivity.class));
and the activity is presented to the user...
If you want to put additional info you can use putExtra("key","value") (it is method from the intent)
you can use like
Intent i=new Intent():
i.putExtra("key","value");
startActivity(context,i);
then in the activity onCreate method you can get this info by
String value = intent.getStringExtra("key");
and like this you can implement your business logic
Edit
when the activity is already running you can use
android:launchMode=["multiple" | "singleTop" |
"singleTask" | "singleInstance"]
I think singleInstance and singleTask will keep only one instance of your activity
Since you're using BroadcastReceiver there is no reason to use startActivity() as Lukap suggests. Simply use the receiver to actually receive messages.
When the SMS have arrived and you want to update the UI, do something like this:
Intent intent = new Intent(SOME_FANCY_NAME);
String msg = String.format("%d new SMS(s)!", numNewSMS);
intent.putExtra(SOME_FANCY_NAME_EXTRA, msg);
sendBroadcast(intent);
Then, in your activity:
class MyMessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(SOME_FANCY_NAME)) {
// Here goes your UI-updates
String msg = intent.getStringExtra(SOME_FANCY_NAME_EXTRA);
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
}
}
In my Activity when the user says they want to enable notifications I call the following method:
private Intent buildRegistrationIntent(boolean register) {
String intentName = "com.google.android.c2dm.intent." + (register ? "REGISTER" : "UNREGISTER");
Intent intent = new Intent(intentName);
intent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate
intent.putExtra("sender", "xxxxx#gmail.com");
intent.putExtra("TEST", "test extras");
return intent;
}
In my C2DM BroadcastReceiver I have this:
#Override
public void onReceive(Context context, Intent intent) {
log.fine(Boolean.toString(intent.getExtras().containsKey("TEST")));
log.fine(Boolean.toString(intent.getExtras().containsKey("registration_id")));
if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
handleRegistration(context, intent);
} else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
handleMessage(context, intent);
}
}
The problem is, the "TEST" extra never gets sent to the C2DM BroadcastReceiver. The output from the below lines is "False" then "True" i.e. it has the registration_id, but not TEST.
Is there any way to pass some user defined data to the BroadcastReceiver or does the C2DM infrastructure eat the original intent and create a new one with just the registration_id?
Why you send TEST via Intent?
You need send push notification messages not via intents.
Please look at onHandleIntent(Intent intent) method in C2DMBaseReceiver.java class. You can override method onMessage() in your C2DMReceiver.java class extended C2DMBaseReceiver.java
It looks like this is impossible. Whatever receives the REGISTER intent doesn't pass it on to onReceive.
App A has this BroadcastReceiver in its manifest (within <application>):
And this receiver:
public class RemoteControl extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.w(TAG, "Look what I did!");
}
}
I'm trying to trigger this from App B:
public void onClick(View v) {
Log.w(TAG, "Sending stuff");
Intent i = new Intent("app.a.remotecontrol");
i.setData("http://test/url");
sendBroadcast(i);
}
For whatever reason, the onReceive() in App A is never triggered even though it's broadcasted from App B. What can be the cause of this?
EDIT & SOLUTION: I forgot to write that I used setData() on the Intent before broadcasting it. That was indeed the problem: as soon as I removed setData(), the broadcast worked as intended.
Originally I forgot to write that I used setData() on the Intent before broadcasting it. That was indeed the problem: as soon as I removed setData(), the broadcast worked as intended.
I've switched to use putExtra() instead for the Intent metadata:
Intent i = new Intent("app.a.remotecontrol");
i.putExtra("url", "http://test/url");
sendBroadcast(i);