The code I am trying to implement includes a service and an application.
When the application is first launched, it starts the service using the
startService(svc_name) call. Here svc name is an intent pointing to the
class that runs the service.
I want to share a resource(file/socket connection) between the service
and the application. For example one writes to a file and another reads
from it. I am unable to get proper sync between the service and app.
Could you please let me know how this can be achieved?
Thanks in advance.
If your app and service are two independent applications (different .apk files) you can look into using aidl. The aidl allows you to send and receive messages across processes.
But, if your app(Activities) and service share the same process (same .apk file) then you can use SharedPreference, or static members. The SharedPreference is accessible by all threads of your application, and is persistent between runs.
http://developer.android.com/reference/android/content/SharedPreferences.html
It can only handle simple types like Boolean, Integer, Long, Float, and String though.
proper way of communicating with a service is thru RPC.
android RPC library is very easy to work with, just look for Remoting examples in ApiDemos.
Related
As for the other application components like activities,Intent, Broadcast Receiver, i can understand their use case but whatever use case of Service is written in the documentation can be achieved using simple Java class having static members (variables and methods) .
Like if i need a download file service .
I can have a static method which will receive taskListener and other required parameters (eg. url of file) in the argument and download the file async and give the callback to taskListener's callback method.
So why should i use service for that.
Please someone explain me the reason of using service with example
First, a service can be started or bound to from outside the application, if you wish, by having the service be exported. That cannot be done via a simple Java class. This is essential for most of the specialized services (input methods, AccessibilityService, TileService, etc.).
Second, a service raises the importance of a process, telling Android that it is doing work on behalf of a user. This helps keep the process around for longer, before Android terminates that process to free up system RAM for other apps. That cannot be done via a simple Java class. So, for example, while you can download a file using a simple Java class, Android might terminate your process before that download can be completed. This is less likely if the download is managed by a service.
I've written a library starting a service in the background. It runs perfectly in all applications.
In order to reduce the RAM usage, I want to avoid running multiple services for different applications. Actually, it's pretty enough to use only one service to get things done.
Firstly, I've written an AIDL file to make IPC between applications/libraries. Defined the service as exported/enabled with signature permission. Since all applications are the exactly the same service, it's not possible to check if any one is up or down. While binding the service to check the condition of the service, it always creates and destroys the own service because of the nature of BIND_AUTO_CREATE flag. That's why not possible to get any kind of info from the exported service if it's really up and running.
Then, I tried to define a Content Provider to the manifest of the library. My aim is to share the service info through it. It's really good mechanism to communicate between exported service and application main process. But it is not usable for multiple instances. Because applications which gets the content provider info from the library use the same authority and so it's not possible to install the second one. It gives an DUPLICATE_PROVIDER_AUTHORITY error.
What's your suggestion about the issue? Is there any option to create a master/slave mechanism? Is it possible to make the service singleton for the application uses the library project?
P.S: Tried broadcast and shared preferences techniques. But they're not effective to listen the callback from the exported service.
You need to put the Service in an APK of its own. It needs to have its own unique package name (in the manifest) which is different from the package names of any of the applications that use it. This is how you make the Service behave as a singleton. Now you can use AIDL and bind to the Service in order to have two-way communication.
Note that in more recent versions of Android, it has become necessary to start a Service using an explicit Intent (ie: the Component must be explicitly specified, you can't use just an ACTION).
Alternative 1:
If the use case permits I think you should not implement the Service.
Make your client implement a service a call your library code. This
is how MediaPlayer and other default android APIs work.
Alternative 2:
Host the service in a separate app..and download the app when the
first call is made from any client. From here onwards there will be
single service handling all the client request.This is how some APIs like adobe
air/ MDM solutions from Airwatch works.
There is no good way you can control a component which is running in other app,unless using broadcast receivers and all.
The separation of app and service is just frustratingly disgusting.
The app and service do not have access to each other's variables and data can only be made available to each other through the Messenger. This results in duplication and makes the conversion of PC to Android code an absolute, absolute pain.
Is there an API or some trick to make them share data totally transparently, or do I just have to settle for this cumbersome rubbish implementation (which is the answer that I am expecting)?
You should read the Services developer guide, if you haven't already.
There are a variety of ways for Activity and Service to communicate with each other. If you bind the Service to the Activity, you can share data.
You can also create a custom Application object, which would let you share information across app components. A custom Application acts like a singleton.
I'm trying to bind a service from an activity and get possibility to call method of it.
These are in different applications (apk) but uses the same sharedUserId and process.
Since they use the same process, Am I obliged to use AIDL or can I use classic IBinder like for Local Service (described on Android Developer sample) ?
I tried both. AIDL works fine and method for Local Service doesn't works, I have an ClassCastException :
E/AndroidRuntime(17511): java.lang.ClassCastException: com.example.app.MyService$LocalBinder cannot be cast to com.example.app.MyService$LocalBinder
Is it possible to use this method for calling service with two apps in a common "shared" process? Or Is that the use of this shared process still requires an IPC method like AIDL?
If I want to use classic IBinder, it's for keeping my application as simple as possible.
Hope you can help me and sorry for my bad english ;-)
I guess the problem is the following. Even if you use sharedUserId and your applications run in the same process you cannot call methods of your service locally, because your service and application are in different packages. Thus, you can use only AIDL that will create a proxy in your client application.
Your problem is that each app has its own APK containing its own CLASSES.DEX, and classes and interfaces are not shared between them. App1.apk/com.example.Class1 is considered a different type than App2.apk/com.example.Class1. Whether or not they're identical doesn't matter.
There's a few ways you can address this:
1) As you've noticed, you can use AIDL. This is the least efficient mechanism, and obviously limits you to only AIDL-compatible types.
2) You can use Java reflection API's. This is better than AIDL in terms of efficiency, but of course the syntax isn't that great.
3) You can attempt to use custom class loading to somehow finagle it so that both apps have access to the same type. For what you're trying to do, this is going to be more trouble than it's worth.
to understand the AIDL in android, i want one real life example, means the at what scenario of development we need to use AIDL.
by reading the Android Docs ... It puts me in confusion and so many question, so it is hard to read whole doc for me, can anyone help me
is it for communicating with outside the phone.
or to communicating with different apps, (why we need to communicate with other apps)
what kind of service they are talking in docs
AIDL is used for Binder. Binder is a mechanism to do RPC calls on/from an Android Service.
When to use AIDL? When you need a Service. When do you need a Service? If you want to share data and control something in another application, you need a service using AIDL as an interface. (A Content Provider is used when sharing data only).
Services can be used within your application as the model roll in the MVC-pattern.
AIDL is Android Interface Definition Language. This basically allows you to do IPC calls.
Use: There are situations where one process would need to talk to other to obtain certain information.
Example: Process A needs info of Call status to determine whether it needs to change Call Type (for example Audio to Video Call or Vice-versa). You may get call status from certain listeners but to change Call type from Audio to Video, Process A needs a hook to change. This "Hook" or way of changing calls is typically part of Telephony Classes which are part of Telephony Process. So in order to obtain such an information from Telephony process, One may write a telephony service (which runs as a part of android telephony process), which will allow you to query or change call type. Since Process A(Client) here is using this remote Service which communicates with Telephony process to alter call type, it needs to have an interface to talk to service. Since Telephony service is the provider, and Process A (client) is the user, they both need to agree on an interface (protocol) they can understand and adhere to. Such an interface is AIDL, which allows you to talk (via a remote service) to Telephony process and get some work done.
Simply put in laymen terms, AIDL is an "agreement" Client gets, which tells it about how to talk to service. Service itself will have a copy of that agreement(since it published for it's clients). Service will then implement details on how it handles once a request arrives or say when someone is talking to it
So process A requests to change call via Service, Service gets the request, it talks to telephony process(since it's part of it) and changes call to video.
An important point to note is, AIDL is only necessary for multithreading environment. You could do away with Binders if you don't need to deal with multithreaded arch.
Another real world example is Google Play License is using AIDL.
I have the same thinking about an example of AIDL, it's very difficult to find an idea to make an example app which uses AIDL. Then I have an idea about it create a LocalLogServerApp. Maybe it can not become a production app but it still shows some value in using AIDL
The main function of this app is
Receive the local log from other local apps (another app need to implement AIDL to send log)
Save the log to datastore
Display the logs
Maybe do something with the local log (eg: search, delete)
Maybe notify developer when error log happened
The benefit of this app
The local log can use when you have some very strange issues which sometimes happened in a few moments and in some specific device. In this case, common Log won't help, debug won't help, Firebase Log may help but Firebase receive log from multiple device.
Reusable, many apps can use it with less code
Hope you find this idea helpful to find another better AIDL example
https://github.com/PhanVanLinh/AndroidLocalLogServer
https://github.com/PhanVanLinh/AndroidLocalLogClientTest
1 - is it for communicating with outside the phone.
Its communicating with outside the app.
2 - or to communicating with different apps, (why we need to communicate with other apps)
As #GodOnScooter mentioned, when your app communicates with telephony service which is actually an other part.
3 - what kind of service they are talking in docs?
This is a service which runs in different process of a system, To bind to this service you need IPC(inter process communication), AIDL is used to implement this.