Fragments, Services and UI: modular approch - android

The goal: create a modular app on which plugin must have UI (that's the key point). I have all info about the main app (the "server") and also about all plugin (all will be made by us).
So we want to give the main apk to user and let him acquire "modules" in order to increase main apk features. He will install the "module APK" which will became visible in the Server app and. Clicking on the module, the user would be able to use the GUI of the module to interact. Ideal would be to have at same time on screen GUI of the server and of the module.
Test 1: having a look at Services. Nice, comunication between the server and clients work fine, but it seems clients (so "Services") are made only for calculation, treatement and so on, but are unable to have form and display. So the "server" have the form, get the data, send them to the service which perfom action send back result and the server display. Impossible to have Activity in a "Service"?
Test 2: Fragment. Nice, but seems the Fragment must be in the same package than the "caller".
Test 3: iFrame. Nice as we can have UI from the Server and from the Client visible at same time and interact with the two. But seem the client class must be in the same APK.
Any idea?
Thanks

Ideal would be to have at same time on screen GUI of the server and of the module.
Android does not have anything "out of the box" that implements this well. The closest is RemoteViews, but you have a limited palette of widgets to choose from and even more limited event handling capability.
Impossible to have Activity in a "Service"?
Correct.
Any idea?
You are welcome to create your own custom equivalent of RemoteViews. In the end, a RemoteViews is a Parcelable description of how to build a bit of UI. Your plugin would pass this to the host app by any number of possible IPC options, and the host app would be responsible for rendering it.

See article about Hexagonal architecture: http://alistair.cockburn.us/Hexagonal+architecture.
Service can launch Activity from it, but you have to allow it in manifest.
Different .apk files (different programs) run in separate processes, so you need to use Interprocess communication (IPC): https://developer.android.com/guide/components/aidl.html.
There is a project on my work - store, which can download different apps. Every app is a separate apk.

Related

How to use app functionality of other app in our app

Before i ask my question i will first explain some background information.
Our company is developing an app for iOS and Android. Our customers can decide to use our app (branded) or integrate our functionality into their app. As our app has some complex algorithms and communication protocols on-board. For this reason we want to provide a kind of SDK for our costumers who wants to integrate instead of using our app.
As we use BLE, NFC and GPS, we decided to make our own apps native. The issue is that many of our customers already have an app which will be a hybrid app in the most cases. So "just" making an SDK for all platforms is almost impossible, not only to build but even more to maintain.
Another important thing to keep in mind is that we want avoid that our customers need to understand our complete communication process, even stronger we won't give our algorithms or communication protocols to others because this is what makes our app/product unique at this moment.
So now the concrete question. Is it possible to provide our functionality as a kind of API so other apps can use the functionality of our app like a kind of API? This means that our app needs to be installed also on the end users smartphone but they don't need to use it individually. The idea is that the app of our customer communicates with our app like an API, our app does the communication with our hardware and gives back the result to the app of our customer. Note that user of the app should not see our app in foreground. (I have the idea from some games who requires "Play Games")
I know there is a way to exchange data between apps (Inter-App Communication) but can this also be used like kind of API?
Obviously this answer relates to Android only. (You may want to ask a separate question for IOS)
At its most basic, a Content Provider is used to exchange data. However, nothing prevents code being run in the provider host to extract that data.
For example, You can host a Content Provider in your app which when called with specific parameters, performs a number of your complex functions and returns a simple table of data (MatrixCursor) or even just a simple True/False response within that cursor.
You could further simplify the usage of this by creating an Android Library that your customers could import into their own project to make it more friendly and API like by adding methods and functions to the library that then delegated their calls to the Content Provider or even to a Broadcast receiver in your main app which could then respond with its own broadcast.
You could even make use of invisible Activities. i.e Call an activity in your app that has no UI.
Even more preferable would be to create your callable code as a self contained library that your customers could use which would negate the need to talk to separate apps completely.
In my understanding, you need other apps to invoke a particular functionality, say call a web API or open an activity and write something or open a popup dialog and do something.
In android: Yeh, it is possible by BroadcastReciever. you only have to listen to the particular action and perform the functionality.
So the task is, you only have to supply the action.

Design for downloading files before starting of an Activity

I have a use case where I want to download some files from the server and store them locally before starting another activity that is dependent on this file. This kind of design can be found on karaoke kind of applications where clicking on one song would
Load the required files from the server
Once the download is finished, open the required activity.
Let us assume that my app is a karaoke app. My question is how to design this flow. Basically, on clicking on one song, I want to show progress on the screen and when the download is finished, I want to move to the activity. Another requirement is that once I am inside the karaoke activity screen and playing a song, I have an option which leads to loading of another lesson. If a user uses that option, I want to again download the required files. Based on this requirement, should I:
Have the file loading thing as a separate activity?
OR
It can be used as Fragmentinside the activity where I choose a particular song. In this case, once entering the karaoke screen, if I choose an option which leads to downloading some files and reloading of this activity, is this the best design?
I would recommend two different approaches depending on how long you plan on keeping the data that you've downloaded. If it is single use than a bound service would be ideal. However, if you are planning on keeping the downloaded content for more than a single use, I would recommend you use a content provider and possibly a sync adapter(Depending on how frequent/predictable content downloading is). This combo would help guide you into not having to think about the 'design' as much(Since it is pretty standard at this point), plus it would provide a lot of features that you may/may not find useful: you can make your internal data 'public' via the content provider/authority(s), you can make an 'account' on the phone associated with your app so that the user can manage its syncing via the sync manager(actually via widgets/apps using the sync manager, but still), and most importantly a set of clean(ish)/standard means to interact with it/propagate UI, etc.
My simple version would be an Activity that spawns either a async-AIDL service with callback (which is in my opinion the only way to use a bound service) that would allow you to asynchronously design your 'starter' activity, its "currently downloading" spinner (which can get progress updates via the callback if you design it that way). Then once the download is complete then send the results (via a parcel file descriptor in the Intent's bundle) to the new activity that makes use of it.
However, if you are planning on using the data more than once, I'd recommend downloading the content like you did above, but then also store it in a content provider for easy access later. Providers also have a lot of nice associated functionality related to cursor loaders, etc. that will help keep a list of the content currently being stored nice and clean/up-to-date/dynamic/etc. However, this is a lot more work to setup once, then later it would save you time in reduced.
A sync adapter is best when the data to be downloaded is predictable, either based on user's account or temporally (such as someone having an account to download data from (email account, etc.) or when the target is fairly constant, but the data should be updated every hour or so(such as the current weather)). So this will depend a lot on your application's exact specifics.
Here is an assignment for an Android App Development course I wrote that is an even more simplified version of the first option (it has intent service + broadcast receiver for returning download results back to the Activity). Obviously since this is an assignment it has sections cut out to make skeleton code, but the documentation is ABSURDLY detailed and should be fairly easily implemented.
https://gitlab.com/vandy-aad-3/aad-3-assg-2/tree/master
Here is the extension of that assignment for that same course that focuses on implementing a simple content provider's 4 main methods (Create, Read, Update, & Delete). Everything else about the provider is given to you.
https://gitlab.com/vandy-aad-3/aad-3-assg-3/tree/master
Obviously the content being downloaded in both applications is probably not what you intended, but that is a simple swap to replace in what you do want.
Not to shill to hard, but here is the (free) Specialization that this course is a part of: https://www.coursera.org/learn/androidapps
Point one : Don't download video file within the Activity level. You can start a Service to handle it. Once the download function is finished you can start the second Activity. While download function is in progress you can show a ProgressBar
Point Two : Best Design is show a ProgressBar with percentage to user. Or disable the function. After download complete enable or start the second activity.

Android : Get Activity/Fragment/Classes of different Apps with same user_id

First time asking on stackoverflow here !
Okay so here's the context. I'm doing an android application, and I'm trying to implement something like a plug-in framework.
My main app's MainActivity's purpose is to manage and launch/show Fragments.
Each of my plug-in will contain (at least) a Fragment and it's layout.
Thus, the idea is to fetch the fragment and put it inside my main app's MainActivity, from it.
So I decided to put my Fragments/Plug-ins into different apps and give all my plug-ins and main app the same user_id. This way all of them are in the same process, and even if they appear in the phone's Application Manager, only the main app is launchable and visible in the Application Browser (which is great).
But here's my problem... How do I get access to my plug-ins Fragments ?
I thought I could fetch some class through the PackageManager and use relfexion to use my fragment, but apparently you can't (or I didn't find how).
I considered binding Services together on each end (Application - Plug-in) but I have no guarantee that the services will bind together. Especially since each app have the same copy of the service, aka not the same Service.
Maybe by using a common .jar to make sure the Services are the same, and thus pass an instance of my Fragment to the main app (yes an instance would suffice).
Or make a CustomClassLoader (but then I might need advice on how to load classes from my other app, because I don't know how to do that...)
I've been running in circles in my head and on the net to find a solution...
To make things clear:
How do i fetch the classe (CustomClassLoader) or an instance (via binding or maybe sharedPreference or wiriting my instance in a file and read it in the main ?) of another app, considering they share the same user_id and thus are in the same process ?
Just because apps share the same user_id this does not imply they are running in the same process. They may and propably have been started by the same process. Sharing resources amongst processes is commonly known as IPC.
AIDL , the android Interface Definition language is a way for implementing IPC. Still this will not allow you retrieve objects from a different application directly but the possibility to invoke methods on remote objects.
But your problem description to me seems more like accessing objects of an jar at runtime in an application. This could be done via classloading.
So your app could retrieve a jar from a Server and load your fragments from it. The definitions of the fragments than would be runtime updateable if you define your fragments completely by code.

Android StartActivtyForResult() from a Service

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.

How to implement multiple screens within an App

I am currently working on an Android App which has different service dimensions, such as " service order", "route planning", "photo gallery" and a central login.
so far i implemented each "screen" (and by screen i mean actually the layout of a screen) as a seperate class, which loads a specific layout and handles all listeners and core functionalities such as calling webservices in a thread, receiving answers etc.
I am not quite sure if this is the best way to implemnt mulitiple layout-screens.
The Android dev guideline proposes to use single activities for each "screen layout". However I doubt that this is the most effective way of doing things. Since i need information for each "layout" which are retrieved by the central login (here: a user object). Since an activity (as far as i understand) is a seperate thread, the passing and retrieving of information seems not very practical.
I would like to get your oppinions/feedback on that and thanks for any hint or tip.
So far my structure looks like :
Activity
loads login layout (res/layout/login.xml with setlContentView)
depending on buttonclick other resources are loaded and initialized (means listeners are added etc.)
Greets
Peter
The dev guidelines recommend that for a reason. It IS the most effective way of doing things. You may complain about having to store your data so it can be passed along from activity to activity, but guess what? You're developing an app for a phone! At any point in time, the phone could ring, forcing the user to switch away from your app. Or the user could just choose to temporarily look at a different app. If your app goes back to square one after switching back and lost all data, the user will be understandably angry.
Don't know if this would be suitable for your app, but another option could be to split off the core data handling into a Service, and have your app be just a UI frontend which communicates with that service.

Categories

Resources