Android StartActivtyForResult() from a Service - android

First I'm sorry for my english that is not so good :).
I am facing a problem to develop my app.
That is a general architecture scheme of my solution.
http://i.stack.imgur.com/ooTmE.png
To be quick, the app has to decode code bare but with two possible ways:
using exernal device (The constructor provides a sdk containing an android Service to communicate with the device),
use the camera of the mobile using the library Zxing which is possible to manage it with intent.
The goal of my own service is to manage some business code and make transparent the choice of the tool for the user.
I believed that was a good solution but I wanted to implement it and I had different problems.
My main trouble is that I cannot execute StartActivityForResult inside the service.
Do somebody have any suggestions for my problem whether a change in the architecture or a solution for the main problem?
#Laurent' : You have totaly right my service acts as an API adapter.
I will try to make the expected behaviour more clear.
I have an app that needs to recognize (real) objects which have QR codes on their top. This recognition action will be done several times by the user during the life of the app.
The user chooses to launch the recognition by clicking on a button (or otherwise but he knows that the recogntion will start). So no notification is needed.
The thing is he doesn't choose the way to do the recogniton. It is why, as you said, I implement an adapter.
The adapter chooses between :
Camera mobile or external device. The first is an activity coming from the Zxing library. The second one is a service that manages the external device. This service provides an interface to get back result.
One more thing, I need that my whole implementation (adapter and co) can be re-used by other apps that will also need to do recognition.
So my thought was to implement a service as an adapter to answer my two conditions (make transparent the choice for the user - and make the recognition available for other apps).
I hope you understand my problematic.

Given your architecture, your MyOwnService must act as an API adapter : it should provide a unified scanning API and address each external service specificities transparently.
Your expected behaviour is not clear enough to provide a solution that suits your needs but here are a few remarks that can be of some help.
Passive scanning:
Even if there are some workarounds : no activity should be launched from a service (not directly). Never. Bad. Services are background stuff, the most they will be permitted is to hint users with Notifications (this is point 2 of Justin excellent answer).
As a consequence there's nothing as a 'popup Activities' (and that's good!). If you need to continuously scan for barcodes, even when your activity is not run, then the only way to warn users is by using status bar notification.
Active scanning:
Inside your own activity you can bind to your wrapper service and make it start scanning for codebars. When it finds one it has to message your activity. Your Activity message handler has complete access to the UI to inform the user of your findings.
You selected Active Scanning in your edit, your problem is therefore to find a way for your service to actively notify your main application (the one that started the active scanning) that a new item has been scanned successfully.
You do NOT do this by starting a new activity (remember: this is bad) but you can bind to a service and/or use Messages between the wrapper service and the application.
I advice you take the time to read (and more time to comprehend) this android developer article on BoundServices and especially the part about Messengers.
A full example of Two Way Messaging between a Service and an Activity can be found in the following android examples : Service & Activity
Warning: designing robust, full blown AIDL-based services is a tough job.

Two ways you could solve this problem.
1) Have MyOwnService do a callback into MainActivity telling it to launch your ScanActivity.
- This is a better approach if MyOwnService's task is only going to be running while MainActivity is running and if the user would expect the ScanActivity to come up automatically.
2) Have MyOwnService create a notification that will let the user access the ScanActivity.
- This is a better approach if MyOwnService's task might be running longer than the life span of MainActivity. That way, you can let the user know, unobstrusively, that they might want to access the ScanActivity.

So finally I changed my architecture.
I make the choice to delete myOwnService and to create an intermediate activity that will be my API Adaptater.
This activity will have a dialog.theme to look like a dialog box indicating that a recognition is under execution.
If the recognition uses the external device this activity will stay at the foreground otherwise the camera activity will start (Being managed by the intermediate activity).
Thank to that I can manage my result from the intermediate activity and do not have an android strange architecture, keeping my business code for the recognition outside my main app.
Service was not the good choice.
Thanks a lot for you help and your time.

Related

Understanding memory management for services on android

I'm newbie in Android services and I need some help. I'm trying to understand the google's guide, but it really lacks lot's of information and i hate the fact that google automaticly translates to my language and doesn't allow me to DENY it, so i cant quote it here.
https://developer.android.com/guide/components/services
I've an app that perform long tasks on background, so I do understand that i need a service to achieve that since activities and related thread or resources might be killed by android when the app goes background.
My service monitore some stuff from user social media so i do need to use social media Apis to contact with their server. To make things easier i wrap the social media apis into one facade and my service deals only with that facade. this facade is a singleton
the user logs in-> the service starts to run in background -> at certain point the user leaves the app now starts the problem...
after the user left the app, my background service keeps running: OK
all its fields still aren't collected by GC: OK
but the inner fields of the facade singleton get released by GC and at certain point my service call singleton (not null) which calls some field that now is null: PROBLEM
how can i deal with that? how can i force android to keep those fields (aren't many) alive because they are being used by my service
PLEASE- do not ask me to make them parceable or something like this... it is a third party api i cant change

Activity, Service and what kind of communication between?

I'm trying to develop an Android application consists of an Activity and a Service. The Activity launch a process on the Service of indefinite duration, which will be closed from Activity. Do not use then the subclass IntentService, but directly Service. Controlled by onStartCommand and OnDestroy.
I obviously need to pass information from the Activity to the Service: the status of the Service and some strings.
I tried to use LocalBrodcastManager, but when turning the devices or when the activity goes in state onPause, the message will lost. I tried to follow several examples, but with little success. This in particular I could not complete it because of some missing information, evidently deemed obvious, but which are not obvious to me: https://developer.android.com/training/run-background-service/report-status.html
I then tried to use Messenger via IBinder ( Example: Communication between Activity and Service using Messaging ), But the program seems a bit complex and I can not able to fit my needs.
What I need is to launch the service from my activity (possibly make binding automatically?, in case of Messenger use), the Service should signal the Activity to be active, then Service records some points via GPS LocationListener, writes it to a file and should point out, again the Activity, the data that is recording, the file size, etc.
What do you recommend to use to pass this information and can you provide to me some example?
I am actually in the midst of a tutorial explaining and comparing many different approaches to IPC in Android but since it's not ready and because you need an easy fix i'll recommend https://github.com/greenrobot/EventBus.
Also feel free to look in an old but still relevant example me and my friends made a while back here: https://github.com/RanNachmany/AndconLab
Goodluck.

Why to use bound (not-started) services within the application process?

As everyone might know, there are two primary types of services in Android: started and bound (I'm not counting started and bound services, as they're mostly the same as just started services).
You can find tons of tutorials on how to use bound services or how to bind to started service, but there are actually no answer on why would anyone use bound (not-started) services within the application process (in other words - without IPC)?
Is there any (hidden?) profit from using bound service (let's say for some sort of processing) over using standard threading tools (AsyncTaks, Executors, plain threads)? Would it worth boilerplate code for connection of such service?
Some context
Question appeared after digging through sources of Google Camera. They're creating a bound (once again - not-started) service for saving images. What is the point? Why not just used some Executor? Am I missing something important?
If that is a bound service, then there is no way it would help to persist saving progress while device configuration is changing (i.e. device is rotated). So I see no advantages.
Started Service is useful in case where there is need for no or very limited (one-way) interaction between starting component i.e. Activity or BroadcastReceiver, and the started service. For instance, a fire-and-forget background download. You give the downloader service a URL, start the service and forget all about it. The only way the downloader service ever interacts with the user is using Notifications. The Activity might as well go on the backstack in the meantime, you don't care. Note that in this case, the service is serving the Activity which started it, and there is no requirement for it to be available generically to other Activities.
On the other hand, bound service is a more generic service or one that needs to serve multiple activities, and more over, needs multiple bidirectional interactions i.e. Activity sends a message to Service, then Service sends a message back to Activity and so on. Consider the example of background music player service, where you pass the music file or remote stream URI/URL to the service, then another activity could change the volume or switch to another track etc. A message back from service to activity could be that the mp3 file is incomplete or corrupted, or a track completed message.
In fact, I came to this question looking for the answer to this exact question, but found the answer quite satisfactorily and complete in the link provided by #SagarPikhwal. Admittedly, I'm a newbie as far as Android programming is concerned, so the above is all as per what I understood !
Edit:
Realized that I didn't answer (to the best of my abilities), the other part of the question about the code you saw for Google Camera. I think the reason why they create a bound service is because Camera is a common shared resource, and there could be multiple users of that system resource simultaneously. The activity using the camera service to capture an image or video is not the exclusive user. The Google Camera application is yet another user of the camera hardware, while there could others, and all of them served by the bound-service.

Is there a way to create a controlling instance that controls several activities of my app?

I work on a project that has several developers.
We work on one rather large app.
Every developer has several activities that can be seen as sub-apps of the whole main-app.
I do realize, that this may not be the best design, but it exists and we have to handle it somehow.
Now the main issue is, that we need a master, that is always active and checks I/Os etc and that can give out status changes to every sub-app/activity. Something like "we just lost internet connection" etc.
Right now, that master is a singleton, that is first instantiated by the launcher activity and that every activity/sub-app can register to by passing the appropriate interfaces depending on what updates the activity would like to receive.
This is working, however it doesn’t feel right, because the singleton needs context to access system resources to determine system stati like internet or gps. Should the singleton be killed by OS, than a simple "getInstance" wouldn’t do much good, because the singleton would somehow need to acquire a context. I've read about extending the Application class and creating a static member context there, but this variable had to be volatile AND its possible that it returns null if the entire app is in some restart-after-crash/kill state. It doesn’t feel safe.
In addition, there should also be a possibility that the master somehow opens a user-dialog to display warnings etc to the user. Those warnings should look the same across the entire app and no dev should have to worry about when or why it suddenly pops up. Right now, those messages appear as custom toasts that overlay everything. Of course they require context and if the app is about to close there could be a problem.
All in all, that’s the mess we are in and I’m looking for a solution.
So how do I create a safe master object or activity (or even service ?!) that can pass info to different activities and post warnings etc (and Maybe even has the ability to close activities or at least order them to close themselves without the need to register a can_close interface).
It should be that safe, that if after a crash android only restarts the activity that was active it somehow manages to also be restarted or at least have/give the same info as before.
Every idea is welcome but total overhauls of the app are just not possible (lack of time and manpower)
Here are a few ideas:
Create a Service component for all the monitoring you need to do.
If I understand correctly, this service will be required only if
some of the activities are running. So you can make it a bound
service. Let all activities bind to this service when they start
and unbind when they close. The service will be started when the
first activity binds.
Create a base class for all your activities. You can write all the common code here. e.g. the code to bind to and exchange messages
with the master service. This class can also contain utility methods
for notifying user etc. So all activities will use the same method
for notification.
For user notifications, you could either use Status Bar Notification or create a Fragment which can capture, aggregate
and display the notifications. You can have a common menu item
implemented in the base Activity class to show/hide this Fragment.
If you use Status Bar Notification, make sure you use one aggregated
notification for your app. Otherwise, the different activities might
create a clutter in the status bar.
I guess that one solution would be to create a service that serve as the master.
You will have to make it run independently of the different activities (but don't forget to manage own to shut it down neatly if the app is no longer used, you don't want to kill your clients battery).
A service can't act on the interface though, so you will probably need to broadcast messages to the activities to order them to open a dialog.
A final thought : Toasts are ok but popup that block the interface are very bad, especially on a mobile device.

Android share location service between multiple map activities

I'm writing an application with 3 mapactivities, and i've implemended a local service(like google tutorial) that recives update from location manager, to share location data from gps between these activities.
Now i want to put every activity in separated process to follow google's suggestion.
So my question is how I have to proced??
Implement and AIDL interface for remote services or register every mapactivity to location listener??
Thanks for answers and sorry for my bad english :P
If it's just a single application that needs location information, then using a remote service and AIDL is an unnecessary complication. The easiest way would be to have a local service with which the activities can bind, then have the service use sendBroadcast() to send location information. The activities can then register a BroadcastReceiver to pick up this data.
First the rationale:
That quote in the Javadoc is a bit... weird. If you understand "running" as being between onResume() and onPause(), then normally two Activities belonging to the same Application cannot "run simultaneously". You would probably have to mess with the Application class or the OS itself to have it behave otherwise.
To wit, I'm actually developing an app at the moment that uses several MapActivity subclasses and haven't encountered any problems so far (i.e. 40+h of development and testing, both on emulators and a device).
Therefore I would suggest:
Try to implement your app as a single-process activity with a local service and just run with it.
If you don't want to do that (can't blame you ;) ), or you encounter any problems, I would suggest starting out with a MapView, perhaps encapsulated within a Fragment. Here's a discussion to get you started.
In short, due to Android's practical fragmentation, keeping your Activities in one process and commiting more time by starting with a more bare-bones implementation will be a safer, ultimately less time-consuming and probably more efficient approach than artificially splitting your app and potentially gritting your teeth on the IPC. At least in my opinion.
After some research i think the best way is to implement IPC with a messenger like described in Android doc http://developer.android.com/guide/topics/fundamentals/bound-services.html#Messenger.. I'll test this solution an report here the result..
Best tutorial is http://developer.android.com/reference/android/app/Service.html#RemoteMessengerServiceSample where is implemented a 2 way communication from client and service..

Categories

Resources