How can I send data from a Service to an Activity? Broadcast receiver? Handlers? Intent? I have several Strings in particular that I would like to send from Service to an Activity, so that I can then display some View to the user.
getApplication().startActivity(new Intent()) ?
Since both Activity & Service is in same application. Instead of going for Service Binder IPC, try implementing register callBack mechanism. Try follow below step.
-> Make a static class which extends from class Application to make quick reference anywhere in your application.
-> Register a callBack from Activity to this application class.
-> Post event from your service to the application class and let Application class deliver the event to all register callBacks.
As #justin-shield mentioned the best way is to use some form of IPC. I don't think you need to use AIDL, however. You can see another answer I gave to a similar question that outlines the basic steps to register Handlers and Messengers in your Activity and your Service.
I think all your answers are way more complex than what I need. I think I have come up with a rather simple solution (psuedo-code):
Service:
Intent i = new Intent(this,Activity.class);
i.putExtra(name,value);
startActivity(i);
Activty:
private Intent intent;
private String s1;
from the onCreate(Bundle savedInstanceState)
{
super(savedInstanceState);
intent = this.getIntent(); //Gets the intent that started this Activity.
s1=intent.getExtras().getString(name);
}
Would I use same code in onStart() ? What about onResume() ? onRestart() ? Lastly, I only want to send to the Activity some data to publish via some View objects, I don't need any communication going back to the Service.
Related
I have read this answer here and also this here and I'm trying to figure out what fits best for my case.
I start a Service inside onCreate() where I make an HTTP requests and I get an id as a response. I then broadcast this id and receive it in my activity.
The problem is that the user can obviously navigate to another activity just by opening the drawer and selecting an option and I can miss the broadcast.
I can obviously have all my Activities extend an abstract class which extends Activity like is mentioned here but I'm not 100% sure its the best solution. What if user decides to quit the app before I receive the id ?
Edit : app architecture
User captures an image using an Intent to open camera app and get the path of the image file.
FormActivity starts where user can add some details about the image.
User clicks upload and I pass the data user has just entered to QuizActivity.
In onCreate() of QuizActivity I start an Service where I :
create an empty entry to server and I get an id as a response and
upload image to server
That id I get as a response from server I then broadcast it.
QuizActivity has an entryIdReceiver registered where receives the id and stores it in a private field until user decides to either leave the activity or click to upload the quiz ( if he entered data for the quiz of course )
If user clicks upload I start an IntentService with the id and the quiz data.
If User opens drawer and select another Activity or clicks cancel to create a quiz I start an IntentService to upload the id with the "empty quiz data" and move user to MainActivity.
The problem is : what if uer closes app while on QuizActivity and I haven't yet receive the id, or user decides to got to another Activity using the drawer without adding a quiz. I still have to start a service and upload the id with "empty quiz data".
It's pretty good, by using abstract class, where you handle all action, and just send callback to your activity. Using that example in your question above seems to me like EventBus.
And even better using special class and interfaces, instead of abstract class, because you may want use FragmentActivity, AppCombatActivity, etc.
For example, your have your own class, which receiving result from your service and send all registered to him activities. Invoking result from net requests with interfaces:
public class NetRequestReceiver extends BroadcastReceiver {
private List<Activities> registeredActivities;
public static void getInstance () {
//Continue singleton initialing!
//....
}
#Override
public void onReceive(Context context, Intent intent) {
for (Activity act : registeredActivities) {
if (act instanceOf ReceivingCallback) {
act.onReceiveMessage(intent);
} else throw Exception("Activity missing ReceivingCallback");
}
}
public void registerActivity (Activity, activity) {
if (!registeredActivities.contains(activity)) {
registeredActivities.add(activity);
}
}
public void unRegisterActivity (Activity, activity) {
if (registeredActivities.contains(activity)) {
registeredActivities.remove(activity);
}
}
public interface ReceivingCallback {
onReceiveMessage (Intent intent);
}
}
Then in all you activities add next listener. But (!) don't forget register receiver above in you Service for receiving result!
public class MainActivity extends Activity implements NetRequestReceiver.ReceivingCallback {
public void onStop () {
super.onStop()
NetRequestReceiver.getInstance().unRegisterActivity(this);
}
public void onResume () {
super.onResume()
NetRequestReceiver.getInstance().registerActivity(this);
}
#Override
public onReceiveMessage (Intent intent) {
//put here whaterver you want your activity
//to do with the intent received
}
}
What do you think, we get, using design above? We now have single Receiver and Callback as an interface. So you can use Fragment, Activity, FragmentActivity, and other class, for receiving result from Service via Broadcast and (!) without copy pasting same behavior!
Also it's looks nice, because we split of different layer - presentation, view, and receiver. You call net request in Service. This Service send result to Broadcast, and then he sends data to all registered activities.
Yes, it's seems like EventBus, but based on your question it's just what you need for listen connection from service to different activities, and with better structure.
Maybe you can send a sticky broadcast. The system will keep it even the activity destroyed and you can receive the intent immediately when your register property
receiver.
But notice sendStickyBroadcast is deprecated and don't forget declare
android.permission.BROADCAST_STICKY
in your AndroidManifest.xml if you decide to using it.
I get intent for push or custom scheme in A activity.
I'm handling them in onResume.
It seems the intents are not disposed unless explicitly told.
I start an activity for intents, and when I close the started activity, it keeps restarted (I suspect this is due to the living intents)
How should I dispose them?
Are there better way of handling for example, push intent?
(without the need to disposing them?)
--- edit
I think my problem is due to the way I handle push, (or scheme)
GcmIntentService creates notification which would start a MainActivity
MainActivity then look at args and starts appropriate activities.
I guess the more conventional way is to go from GcmIntentService to appropriate activities directly?
Try putting this inside onCreate() method of your MainActivity.java :
if (savedInstanceState == null) {
final Intent launchIntent = new Intent(MainActivity.this, AnotherActivity.class);
startActivity(launchIntent);
}
If the activity is already created, rather put this inside onStart() method.
I have two applications.
One app has the Activity and another one is a background service.
I can able to access the service app from my activity app using implicit intent filters.
I need to receive a result from the service.
For ex:
From activity app, i am going to start the service and send a data.
In the service app, i need to receive the data and do some inspections and need to return to the activity app as modified result.
I can able to send by putExtra and can able to retrieve it in the service by getExtra. I need to return a value from service and receive it in activity app.
PS: The thing i needed is, the same way what we do with finish() and onActivityResult() with the Activity results.
Thanks in advance to you masters...
First add a class like this:
package com.test.context; //For example
public class MyContext extends Application
{
//Here you define the attributes to share through the application
// with setters and getters
}
and in the AndroidManifest.xml, add the path of the class,
in the example is com.test.context so:
<application android:name="com.test.context.MyContext"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
Then in your code you can do some like this:
MyContext ctx = (MyContext)getApplication();
And you will be able to share data in all the app, btw activities and services, i did it this way in a Tasker , and works fine.
Why do you want to communicate through intent while there is a perfectly working binder protocol.
http://developer.android.com/guide/topics/fundamentals/bound-services.html
If an activity starts a service with 'bindService()' then the service will run until the activity calls 'unbindService()'.
I have a Main-Activity which displays several spinners.
With a Toggle-Button in the Main-Activity I start a service which collects GPS-Data in background that measures the distance and sets some other variables.
When I stop the service with another click on the Toggle-Button in the Main-Activity, I stop the service, so the onDestroy() command is executed in the Service.
Within onDestroy in the Service, I want to submit the variables from the service to the already opened Main-Activity.
I tried that so far without success in the service:
Intent intent = new Intent(this, Main.class);
Bundle b = new Bundle();
Test = 2222;
b.putInt("Test", Test);
intent.putExtras(b);
I do not use the "startActivity(intent);", cause the activity that should the data send to is already open...the Main-Activity.
And on the side of the Main-Activity:
Bundle b = getIntent().getExtras();
if (b != null){
Test = b.getInt("Test");
}
else{
//..oops!
Toast.makeText(Main.this, "Oops...Nothing from service! :(", Toast.LENGTH_SHORT).show();
}
I never get data from the service.
I am trying this cause I need to start the service from the Main-Activity, from the Main activity the user stops the service and gets the values from it, then the Main-Activity should transmit the values from the service AND from the selected spinner values from itself to another activity.
I am trying that now for days and I also find some hints here, but nothing worked for me so far.
Someone any ideas?
Do I have to use a Broadcast-Receiver?
Whats the correct way to do this?
Before destroying the service store the data in shared preference and access it in the main activity
I don't know if this is the best way, but just have the Service you created update a static pojo. If the activity is already open then you could just set a timer to poll a the static pojo from the Activity to see if something has changed through an AsyncTask. When something has been updated in the pojo the AsyncTask can tell the Activity to update the UI accordingly. Then you don't have to play around with silly bundles. Also if your worried about your data getting lost you could always use SQLite. Hope this helps.
You need a broadcast receiver in main activity to get the data.
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.