Android: how to call a non-static function from C2DMBaseReceiver? - android

I am using android-c2dm, and my device successfully receives messages from it. I want to call a non-static function (in an already-existing Activity) to do something with that message, but simply calling it from C2DMBaseReceiver is illegal. How can I transfer this information back to the activity?
Edit: What if I call a static function to assign variables (or set Shared Preferences), then call a handler which will use those variables to do what needs to be done? Is that bad style?

What you could do is put the message details in an Intent somehow (the crudest way would be serialize the message to a String and add it as an Intent extra) and then send that Intent to the Activity using startActivity. The Activity could check for the extra, know that it is a message, extract and deserialize the message and then go to town.
You might need to set the appropriate launch mode or Intent flags if you want to make sure that an existing instance of the target Activity receives the message.

You can get message from Intent in onMessage method, then show Notification and startActivity after user clicks on Notification. You can use Intent flags for bring background activity in foreground.
So if activity is not started - it will be started, if activity in background - it will be show in foreground and if it in foreground - then we need only change TextView text.
You also can startActivity without showing Notification.
Also you can use onNewIntent(Intent intent) Activity method for changing text. You can put message from google intent in onMessage into new Intent and startActivity with this intent and FLAG_ACTIVITY_SINGLE_TOP flag.

Related

How do I start an intent without the flag FLAG_ACTIVITY_NEW_TASK in an Android service?

I am trying to connect to different activities from a custom soft keyboard. I need the activity underneath the keyboard to allow data to be sent without the activity creating a new instance of itself. For example: if the keyboard is over the messaging application, I want to send that application data without losing the current conversation that the user is typing into. I currently have the following code to send data to the activity.
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
//sendIntent.putExtra("thread_id", (long) 1);
sendIntent.setType("image/*");
startActivity(sendIntent);
I am getting the following obvious error when I try to run it...
E/AndroidRuntime(6129): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
How can I keep the current activity underneath the keyboard from resetting itself when an intent is sent from the keyboard service? Or more simply, how can I send an intent from a service without setting the FLAG_ACTIVITY_NEW_TASK flag?
You can't really do this like that. A Service can't pass data to an Activity without "starting it". You don't want to do that. You want to pass data to an "already started" Activity. There's 2 ways to do this:
Use a bound Service. Have the Activity bind to the Service. The Activity can then call methods on theService (using AIDL) and receive returned data.
Use a BroadcastReceiver. Have the Activity create and register a BroadcastReceiver to listen for the returned data. In your Service, send a broadcast Intent when you want to transmit data to the Activity.
You can do this by several ways but you must set flag in order to complete task.
If you want to create a new instance and close the current instance you need to set Intent.FLAG_ACTIVITY_CLEAR_TOP.
If you want to reuse the same instance of the activity in this case you need to set both Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_SINGLE_TOPafter that it will not create another instance of the activity but call onNewIntent() of activity to run the new Intent.

In build notification bar in android

Any one can tell me how could i get inbuild notification listner in android. What all i want is if user put password on screen and if then some notification arrives. and if user click on notification, I want password field should be reset.
See http://developer.android.com/guide/topics/ui/notifiers/notifications.html#CreateNotification to create a local notification.
In the intent you use for the notification add an extra bit of data that you define (e.g. "ClearPassword" as a boolean of true).
In your activity, check for extras and your specific extra and if it is set then you can clear the field.
Why don't you just clear the password field in the onPause method of the activity? If the user clicks on the notification, the pending intent will launch a new activity (most in the cases from another application). When your activity is no longer the foreground activity, its onPause method will be called.

How can I know the startActivity intent from other application?

I have an Activity and assume that has been launched. When the other application use startActivity method to start my Activity, my Activity will show and run the onResume Method, but I can't find any way to get the intent which is used in startActivity method by the other application. I want to get the extra data in the intent. How can I do?
EDIT
My Activity is singleTask, and I want to get the startActivity intents form other applications. I think it is not associate with filters.
Have you tried using getIntent() ?
Then you can do:
this.getIntent().getExtras();
After that if you need new intents just override the onNewIntent function in your activity.
I simply say an example. When we need to share something. We click share button which shows a list of app by which we can share our things.
So, if you want to make that kind of app which can receive other app data then you need make your activity capable of receiving that data. In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter in manifest.
Below this link you will get some more information : http://developer.android.com/training/basics/intents/filters.html

Pending Intent: Can I specify a method to run in the receiving activity?

When a pending intent is sent, does it create a new activity? What if I have an activity already running? Is there a way to specify an already running activity, and have a method in that activity run once I send the intent?
What I want to do is have a button in a notification bar that acts a "stop" button, which will call the stop method in the already running application.
It depends on the Activity's declaration in the manifest, or the Intent flags that you include.
For example, if you use FLAG_ACTIVITY_SINGLE_TOP (or the activity has launchMode set to "singleTop") then onNewIntent() will be called on the existing activity instead of creating a new one.
In your example, you should pass an extra in the intent to indicate that you want to execute the "stop" action, then check for it in onNewIntent().
This is well explained in the official documentation about launch modes: http://developer.android.com/guide/components/tasks-and-back-stack.html#TaskLaunchModes
EDIT: However, since the ultimate objective was playing audio in background, using a Service is a more appropriate option. Check http://developer.android.com/guide/topics/media/mediaplayer.html#mpandservices
To control the service from the notification (i.e. play, pause, stop) you need to supply PendingIntents created from with startService().

Intent extras missing when activity started

Inside a broadcast receiver I want to start my app (Activity) and pass in some data.
My problem is that the extras don't seem to carry over into the activity. I am trying to get the data inside the onNewIntent(Intent i) function.
Any ideas?
Here is my current attempt in the BroadcastReceiver:
Intent intSlider = new Intent();
intSlider.setClass(UAirship.shared().getApplicationContext(), SliderMenuActivity.class);
intSlider.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intSlider.putExtra("action", ScreensEnum.Object);
intSlider.putExtra("objectId", objectId);
intSlider.putExtra("objectCode", objectCode);
intSlider.putExtra("userId", userId);
UAirship.shared().getApplicationContext().startActivity(intSlider);
EDIT - Added code used in onNewIntent() and onCreate()
The following code works great in onCreate() when the app isn't currently running. For when the app is already running the same code doesn't work (i.e. no extras) from the onNewIntent() function.
Intent intent = getIntent();
if(intent.hasExtra("objectId")) {
loadDetail(intent.getStringExtra("objectId"), "2w232");
}
The problem is getIntent() method. It always returns the intent that started the activity, not the most recent one. You should use intent that was passed to onNewIntent method as an argument.
We stumbled upon this problem once, when we were trying to launch/call onNewIntent on an Activity in response to a local notification tap. The extras that we put on our Intent were disappearing at the time onNewIntent received it.
I don't remember this being documented anywhere back then, but the "problem" was that we weren't setting the action field on the Intents that we prepared. Turns out if the Intent received by your Activity doesn't have an action set using setAction, the system still delivers the Intent to its destination, but doesn't transmit the extras you have set while creating the Intent.
TL;DR:
If you encounter this problem with an Intent with no action, calling setAction to set an arbitrary action value before sending the Intent might fix it.
Extract from the docs
This is called for activities that set launchMode to "singleTop" in
their package, or if a client used the FLAG_ACTIVITY_SINGLE_TOP flag
when calling startActivity(Intent). In either case, when the activity
is re-launched while at the top of the activity stack instead of a new
instance of the activity being started, onNewIntent() will be called
on the existing instance with the Intent that was used to re-launch
it.
An activity will always be paused before receiving a new intent, so
you can count on onResume() being called after this method.
Note that getIntent() still returns the original Intent. You can use
setIntent(Intent) to update it to this new Intent.
I think the last paragraph explains your problem.
You have to set the flag FLAG_ACTIVITY_SINGLE_TOP or set launchMode singleTop in the manifest file.
Of course when onNewIntent is called you do not use getIntent but the Intent received as argument.
onNewIntent will be called when the activity instance already exists. For example, if last time you pressed the Home Screen button.
I wrote a solution that worked for me here: Intent with old extra in onCreate() for singleTask Activity
You can store the last received intent in a member variable (mLastIntent).
Then you can use this member in your onResume() method to query for your extra data.
private Intent mLastIntent;
#Override
protected void onNewIntent(Intent intent) {
mLastIntent = intent;
};

Categories

Resources