How to startActivity() from BroadcastReceiver without recreating the activity? - android

I need to receive a broadcast event inside a broadcast receiver and than pass this information to an activity that is already open. How can I inform the activity from the broadcast receiver without it getting recreated? This causes a total refresh which is not needed.
Now I could receive intent inside a broadcast receiver that is declared within the activity, but I also need to receive the intent when its in background as well, hence the main place I am processing the intents is in a separate broadcast receiver. So I just don't know how to inform the activity that a new intent has arrived without onCreate() getting called and re-init the whole UI.
I think I need the NEW_TASK flag or it won't run.
PS: What are these insane downvotes about. What could be more relevant than how to start an activity from a broadcast receiver in such a way as not to recreate the activity. BTW, I am going to find an answer w/wo you. Why the bitter downvotes? I suspect it is because you know I could use an answer. Well I'll probably be posting an answer to this great question myself quite soon.

if you want to recreate this activity do this:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if don't want to recreate , just do this:
while this activity on your task's top,intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
declare the actvity in the manifest with: android:lauchMode= "singleTask";

And the answer is .....
declare the Activity in the manifest with
android:launchMode="singleTop"
Still would like feedback on this answer as I notice that in onResume() the intent does not seem to carry over the values as it did before. So I cannot pull out values that I set on the intent inside the broadcast receiver ...
Update: In order to get the values from the receiver you may need to do the following inside the Activity:
#Override
public void onNewIntent(Intent intent)
{
setIntent(intent);
}

Related

How can I send a message from one activity to another in real time

I have two activities, when I open Activity2, the Activity1 won't be closed. In Activity1 I have a handle that post a code (handler.postDelayed()), when this code run I need my Activity2 be notified in order to execute a other code too.
My question is: How can I send this message to Activity2 without reopening it.
I tried use an Intent with a specific action and catch it in onNewIntent() in Activity2; it works but the problem is that this reopen my Activity2. And I can't save the data in SharedPrefs cause my postDelayed() have no fix time, then I'd have to be checking all the time.
Does anyone know how I can send this message when my postDelayed() runs and how I catch it in Activity2 without reopening it? Please if possible post a example or a link to one.
Really thanks...
It was a simple solutions, like said #njzk2, was only add
<activity ..
android:launchMode= "singleInstance" />
or
<activity ..
android:launchMode= "singleTask" />
(both works).
Thanks
You shouldn't be using an Activity to handle long-running code, you should probably look into creating an IntentService to handle your background code. The IntentService can broadcast a new Intent when it is finished running the code. Have your first Activity start the Service, then instantiate a BroadcastReceiver in your second Activity to listen for updates from the Service.
Sending an broadcast Intent doesn't start or resume an Activity.
The BroadcastReceiver for an Activity receives and processes
Intent objects even when your app is in the background, but doesn't
force your app to the foreground.

Differents between sendBroadcast (intent) and startActivity(intent) in android?

When i send a broadcast by context.sendBroadcast(intent1) method with parameter: intent1 and start a activity by context.startActivity(intent2) method with parameter: intent2. What is difference between them. Are intent1 and intent2 implicit intent with define: new intent(action_do_something). Can anyone help me ? Thank a lot
As the names suggest, sendBroadcast will send a message to no particular recipient. It just transmits a message like a radio tower. You have to listen for broadcasts.
On the other hand, startActivity starts an activity(the onResume() of the activity will be eventually called).
The names are saying it all. When you send a broadcast message you need to call the sendBroadcast. but to start activity u need the other method. There is no direct comparision between these two as the purpose of these two things is totally different.
In both case the intent is used for a common reason, first two define the receiver. In the broadcast message the intent is passed to make sure which type of receiver can catch this. And for startActivity it is used to do same but for to make sure which activity will be started. and in both cases intent is used to pass data.

How to bring an Activity to foreground (or create if not existing)?

I am intercepting sms messages with some information in them. Then in my SmsListener I'm creating notification to show in statusbar.
Then, when user clicks on a notification I want
Bring MainActivity to foreground (If such activity does not exist yet it should be created)
Pass to it data from the sms
Perform some ui changes basing on this data in this MainActivity
My activity is defined as
<activity
android:name=".MainActivity"
android:screenOrientation="sensor"
android:label="#string/app_name"
android:launchMode="singleTask"/>
Activity is launched as
Intent i = new Intent();
i.setClass(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Also in my activity I have overridden method onNewActivity
#Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
// I have data from broadcast in intent variable passed to this activity
processDataFromBroadcast(intent);
}
It works fine if the MainActivity already exists but if MainActivity does not exist it is started however onNewIntent was not called
Then I tried to invoke processDataFromBroadcast from onCreate: processDataFromBroadcast(getIntent()).
First time data is passed correctly from my broadcast to the activity.
However if MainActivity is sent to background and then again brought to foreground either onCreate or onNewIntent is called and processDataFromBroadcast is executed again with intent sent by broadcast and thus my MainActivity is updated with data from broadcast every-time the app is bringing to foreground - the latter is unwanted, how can I make my activity to forget this intent after first handling.
Here is sample application.
For an activity to launch only one instance of itself, have a look at the <activity> manifest element, and particularly android:launchMode. You want to configure it with either singleTask or singleInstance.
To pass data to your activity, you add data to the Intent you use to open it. To pass data with the intent, use the putExtra() methods of the intent before sending it off, and getExtra() methods to retrieve them in your receiving activity.
I'm assuming that you know roughly how intents work, but if not you could learn more about intents by taking a look at this Android developers article.
in case your problem is still unresolved, as I was just running into the same issue, here's how I solved it:
I am putting a timestamp as intentId as an extra upon the intent during it's creation. the first time, I am handling the intent in onCreate() or onNewIntent() I am reading the intentId and store it as the last intent handled. so the next time onCreate() or onNewIntet() is invoked I can check the intentId and if it equals the id of the last intent handled, I ignore it! It don't know if this helps in your case, maybe you can adopt it.
To keep intentId independent from activity lifecycles you could persist it in the userdefaults.
I agree that one would expect calling setIntent(new Intent()) in onNewIntent should do the trick.
It it late to answer, but it might be helpful to others looking for the solution.
Just add below lines of code :
Intent mIntent = new Intent(this, SplashActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // You need this if starting the activity from a service
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
Where SplashActivity is the name of initial application that is the first screen of your application.
Hope it helps. :)

Android: calling a method from a Service to an Activity

I have a simple question to solve, but I am not sure how to do it.
I have a class that extends Service that runs a thread looking for a TCP connection. If one comes in, it read an input message.
If the input message is "START", I start an activity, in this fashion:
Intent dialogIntent = new Intent(getBaseContext(), VoIPCall.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.putExtra("inetAddress", clientSocket.getInetAddress());
getApplication().startActivity(dialogIntent);
While this activity is running, the Service keeps running. At some point I may reserve a "STOP". I would like to call a method in the previously created Activity but I am not sure how to interact with it.
I do not want to use a static method. How can I please do that?
Thank you very much,
EDIT: I changed my code to this:
Intent dialogIntent = new Intent("com.voip.rudy.START_CALL");
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
dialogIntent.putExtra("inetAddress", clientSocket.getInetAddress());
getApplication().startActivity(dialogIntent);
And in the manifest:
<activity android:name=".VoIPCall">
<intent-filter>
<action android:name="com.voip.rudy.START_CALL" />
<action android:name="com.voip.rudy.STOP_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<category android:name="android.intent.category.DEFAULT" /> was required to avoid having it crash.
EDIT:
The solution given has fixed my issue but I wanted to actually act on member variables on that class, that are previously initialized. Say I call the constructor, then I would like to go back into this activity and act on the member variables.
The member variables are not initialized when I call one action after another, it seems to create a new activity somehow. Would there be anyway to act on the same activity, and keep the objects intact please?
James
Add the Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT flags to your intent and call startActivity with a new action or a special extra that can identify the intent.
In the activity, write a method called :
private void handleIntent(Intent intent) {
}
call this from onCreate (or onResume) using:
handleIntent(getIntent());
and also write:
#Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
handleIntent(intent);
}
There are a few ways to do it, really depends on the overall structure of your application. All can work. Off the top of my head these are the methods that come to mind
1) Create a custom intent and have the activity or service react to it when the otehr sends it
2) Instead of the service, setup the logic looking for the tcp connection as an async task within the dialog activity, when you have the tcp connection you could pass it off to the service to do its work
3) Take a look at the local service and remote service SDK examples and use the callback code as the basis for passing data back to the activity. You can also call through the interface back to the service.
4) Maybe even setup a broadcast receiver 'architecture'. This has the advantage of decoupling the user activity from the service entirely. You could put some of your application logic in a service in another process, or even in a process that runs at device boot.
I think any of the techniques would work. I'm guessing that the behavior you are seeing is related to the lifecycle of the activities within android and you might need to move some of your processing to the onResume/onPause or onStart/onStop methods. If you you find that your activity onCreate is not being called, but you now your activity is active, it might jsut be that an activity instance from a previous invocation is still alive in the system. If so, it is possible that the OS is using that instead of the new activity that you want. The best way to see if this is a problem is to put some "Log.d" calls at the beginning and end of all of the activity methods that you override. You will be able to tell what is happening by watching logcat. The technique that you use may also be dependent on how synchronous you want the activity's reaction to be with the TCP event. If you want completely async you can go with a standard broadcast, or a service callback with a message send. If you want synchronous then do it with a service callback. In case you haven't seen it this SDK link has a pretty good description of the activity lifecycle http://developer.android.com/reference/android/app/Activity.html

Calling a method instead of an activity using an Intent - android developers

How can I fire a method instead of an Activity in my code?
I want to use the AddProximityAlert() method from the LocationManager but it needs an Intent to work and I don't want to call another activity since the method I want to fire is in the same Activity from where I'm using AddProximityAlert()
Goes like this:
public clase onCreate()
{
......
LocationManager LM; // already initialized
LM.addProximityAlert(lat,long,radio,expiration,INTENT) <--- This INTENT needs to call myMethod()
}
public void MyMethod()
{
.......
}
I have several hours trying to find a solution for this, and all I find is for calling another activity, please be as much specific, even if I have to do something with the manifest.xml because I haven't used intents before.
Thanks
What if you create a android service (or broadcast receiver might be more appropriate) within the same application that handles the intent.
You don't leave the same pid, it's a non-visual service and you never leave your activity?
You can call your service directly by creating a intent the references it's class name directly.
intent = new Intent(context, my_service.class);
It then will hit the services "onStartCommand()" function and you can do your intent processing from there.

Categories

Resources