Let's say a service 'MyService' is already running, doing some work like copying a file in background, before an activity, 'MyActivity' is launched. Then user launches the activity. How can I retrieve what file is being copied in MyService when MyActivity starts so that I can show it in UI?
I haven't attached a code because I want a generic answer to this. The task could be anything, like downloading a file. I'm learning coding and experimenting with services. So, I'm just copying a bunch of big files in a service.
If needed, I'll post the code.
A possible solution to this is to have the service expose a RxJava bus (or similar) where it pushes updates on what it is doing. Then the Activity will subscribe to this bus in onResume and unsubscribe in onPause and will display info based on what is being pushed on the bus.
You could have a single bus, where the event itself carries data (like the percentage of copy), or you could have multiple buses, for instance one for state (idle, copying, ...) and another one for details on the state (like a bus for percentage of copy done).
A possible implementation for the states would be
sealed class State {
object Idle : State()
class Copying(val percent: Float): State()
}
then in your Service you would have
val stateBus = BehaviorSubject.create<State>()
then
stateBus.onNext(Copying(.5f))
Related
So I have a foreground service displaying a few items, I want to perform some function in the enclosing service when I press on an item in the recycler view. I'm aware I can use an Instance of the service, but it's a memory leak. I'm aware as well of the binding/unbinding methods between service and activity, but this I believe doesn't apply to my situation?
Normally everything you would like to execute in the Service should be implemented and then called using a Binder (if Service and App are in the same Process) and its onBind() method.
In your specific case I suppose your Service is the "owner" of the UI created by WindowManager (like a floating window), so:
if Service and UI are in the same Thread, you can pass a Listener/Callback to it or use the common onBind() way
if Service and UI are in different Theads: you need some kind of synchronization between them (Looper+Message, a Queue, etc...)
if Service and UI are in different Process: you need to implement "AIDL" technique
I am developing a testing application on an Architecture which is based on Producer-Consumer structure. I have an producer-consumer* problem, especially if an producer callback mechanism is utilized in android service i.e. consumer. Consumers are not supposed to hold the call for more than the minimum necessary time to have the info handed over. Since the producer’s callbacks are supposed to run in a different thread than the consumer’s one.
In my specific case within the callback of Producer only a reference moving of the passed object should be done and release the control right away. The object has to be consumed in the consumer thread. Currently I have been calling a method which only gets data coming within callback and processes that data and return it via Intent baack to the Android Activity.
Now, Android intents are well known to be resource consuming entities which are not meant (and not supposed) to be used to transfer data streams.
Within the Test app, one intent per callback is generated. Those overflow the whole system. For example, at 25% of load a traffic of about a thousand Android intents per seconds are triggered.
I want a way which doesn't include Android Intents(without any Thrid party jar) using which I can send data back to my android activity or route on host machine at super high rate so that my producer call back doesn't get crashed.
Use a socket connection between the Service and the Activity for streaming data. Intent is the wrong technique.
My app makes use of various heavy libraries and data files, that need to be loaded / synchronized with local storage on start-up. As this operation takes some time, I was thinking of creating a dedicated activity for this purpose. This activity would be the entry point of the application and would do the following:
Display a background image and progress bar
Process necessary data (and updating the progress bar accordingly)
On completion, launch a new activity
Here is a couple of questions:
My initialization activity needs to pass a reference to the data to its child activity. Ordinarily I would do this with setSerializable, but here I am using 3rd-party non-serializable classes.
So I was thinking of simply making the data static. Is this a good solution? Any chance the static reference might break when switching activities or during the application life-cycle?
public class LibraryInitializer {
private static Some3rdPartyClass myLib;
public static void initialize(){ // Called by initialization activity
myLib = Some3rdPartyClass.create();
}
public static Some3rdPartyClass getMyLib(){ // Called by child activity
return myLib;
}
}
I need the initialization activity to be called only once. How to prevent that it is shown again when a user clicks on the back button?
More generally, is this approach okay, or would you suggest a better one? (I also considered using one single activity, but adding/removing the progress-bar and background dynamically)
Long running code really ought to be done using Android services. I would recommend doing your complicated logic in a service that your various "Activity" classes (which correspond to the views of your application) simply consume. Services can outlive the UI of the application and can also be started / initialized in response to various other events (like system boot), even when the user is not interacting with the application whereas an Activity is very tightly intertwined with the presentation.
In terms of loading / syncing data, I would strongly recommend against putting this logic in your activity code... instead, use a SyncAdapter or one of the other scheduling mechanisms for syncing. This will ensure that syncing activity is batched with other uses of the networking chip, which minimizes overall battery usage, and also allows you to have synced before the user is actively using your application, so that you aren't keeping the user waiting when they open your app.
When you start a new Activity from the loading Activity call the finish() method to close that activity and it will be deleted from the applications activity stack. like below:
startActivity(intent);
finish();
For the question for passing data through activities, extend the Android Application class, where you can define the global state and variables of your application.
I have started to use the event bus library Otto for updating the interface (activities) from different components in my Android application. For instance, when a change to a Model class is made, I post to the event bus or if an AsyncTask has finished, I post an event to the event bus in the onPostExecute method.
So far I am using one event bus for user interface updates. I noticed that even paused activities receive these events yet. In the documentation it states
The paused activity does not receive user input and cannot execute any code.
Which I find controversial, I can only explain this, that this code is of course executed on a different thread, but still in the activity.
My question is, does this usage result in any disadvantages? Having multiple activies being paused, executing events, updating elements of (paused) activities or ignoring them. Does this result in a noticeable overhead or can I ignore it?
Is there a different approach when one wants to use event bus for updating the interface?
Does this result in a noticeable overhead or can I ignore it?
That is impossible to say in the abstract. It will depend on what work you are doing and how often you are doing it.
Is there a different approach when one wants to use event bus for updating the interface?
There is no requirement that your activities and fragments be listening for events while they are in the background. For example, you can register for events in onResume() and unregister in onPause(). You can then use other techniques (e.g., Otto's #Producer pattern) to update your activity's/fragment's UI en masse when it comes back to the foreground in onResume().
I have a small Android app that I have been working on that logs GPS data to my SD card in a GPX file. I currently have a main Activity that starts a Service to do all the background work. The service is kept in the foreground in the notification bar to make it the least likely thing to be killed by the OS. Currently I am requesting location updates from the service at the maximum frequency to get the most accurate route. The problem I am having is my User Interface is acting slow/strange. Correct me if I am wrong, but what I have concluded is that I have too much going on in the main thread of the app. My next thought is to try and move the service performing the acquiring and logging of data to a separate thread. I am new to Java/Android so the whole topic of interacting with separate threads is hard for me to wrap my head around. Initially in research I came across IntentServices, which are supposed to make threading easier, but from what I read these don’t seem to mix well with the Android location package because they don’t run long enough. I feel like I am running in circles with internet searches on this topic. I desperately need some guidance on how to achieve the following features for my programs service:
Separate thread from Main Thread
Fetching and storing of data must be the least likely thing to be killed by the OS and run indefinitely once started (don’t worry about battery I will have the device plugged in to power while running the app)
Eventually I will need the ability to interact with the User Interface
Thanks for any help you can offer!
this is a common problem that i have accomplished a lot on
in the launcher or main() ( what Android is calling an Activity ) you do as little as possible ( which amounts to saving the the refs they give you and maybe setting a few other things as long as you are there ) and do ^not^ drop in to a long-running activity
A Service is exactly what you need but instead of trying to pump it into a "hold on to it" state what you do is implement checks for nulls and handle as needed -- trying to "fix" a machine to make it run the way you want here actually involves rescinding you hold on the main thread and letting it go as fast as consistent with the Applicaton's general constraints.
To do this you can simply write a Service - reading everything available - then extend that service and implement Runnable then you run the constructor on that code from the Activity Constructor and do new Thead(yourClass).start(); in the onCreate() checking for Thread.isRunning() before starting it again ...
Service will have an onCompletion() call in it somewhere - it will go through an interface
All this is done in Android in something like start activity for result then you just to the UI stuff in that call or sorta figure out a way for the GUI to get called somehow at some time then check to see if Service is done an so report in the gui