I've got a question about android applications with same android:sharedUserId and android:process attributes.
would you please tell me, when should we use applications in the shared process and how can we access data on other application in that process?
android:sharedUserId - This is deprecated now, you should avoid using this
when should we use applications in the shared process
Ideally whole application process should not be shared with another application and there won't be much use-cases of it as well
Android components such as Activity/Receiver etc should be made to run in a separate process as opposed to application process basis some use-case, like we used separate process for running our FCM service to reduce memory footprints while initialising reducing our ANR's
how can we access data on other application in that process
You can use Android Interface Definition Language (AIDL) for this
https://developer.android.com/guide/components/aidl
Related
I found three ways to share data across applications.
1.Content Provider
2.SharedUserId-When you declare the same shared user id for more than one application, they can reach each other's resources (data fields, views, etc.). provided applications are signed with same certificate.
3.Global Process-Put a component of one application in separate process by using android:process attribute and naming process starting with lowercase letter and another component of another appication in separate process with same name as the separate process of first application.Now these components can share data.
I am confused what to use when or which is more efficient?
I found three ways to share data across applications.
#2 and #3 are the same, insofar as #3 (shared process) requires #2 (sharedUserId).
You also missed all other forms of standard Android IPC, including:
starting activities
starting services
binding to services
sending broadcasts
I am confused what to use when
Ordinary app developers should use #1 (ContentProvider) or one of the other standard Android IPC mechanisms that I outlined above. You have no control over when users update apps, and using formal IPC enforces a clear separation between the apps, forcing you to think through things like API contracts, API versioning, and related concerns.
sharedUserId and shared processes are really there for device manufacturers, where apps are pre-installed and then updated in unison via a firmware update. Personally, I recommend to device manufacturers that they too use standard IPC, for most scenarios. For example, if App A modifies App B's files directly, how does App B find out? What if App B then overwrites App A's changes, because App B did not know about those changes? In many other areas of computer programming, we have gotten away from having multiple processes from multiple apps work with each others files directly.
which is more efficient?
Efficiency should not be an issue in this case, as you should be using any of these techniques infrequently. If you have two apps that need to communicate with each other frequently, then you really have one app, and you should implement it that way.
From Firebase docs they say:
Multiple processes
Crash Reporting creates a separate background process to upload crash
info. If your app extends the Android Application class, you must
ensure it is multi-process safe. Otherwise, it may cause concurrency
issues. When an app extends an Application object, this object gets
instantiated for each process in a multi-process app. Two important
things to watch for are:
If the implementation of this object accesses any out-of-process state
(a database, the file system, shared preferences, etc), or performs
other actions not safe for a multi-process environment, concurrency
issues might arise. This is because multiple instances of the
Application object may run simultaneously. Many third-party libraries
keep out-of-process state (e.g. in a local database) and are subject
to the same concurrency issues if they are initialized from the
Application object. If your app fits the description above and you
plan to use Crash Reporting in your app, we strongly encourage you to
consider moving the Application logic to Content Providers, or to
Android Activities. Any Application logic that is not safe for a
multi-process environment can have unintended effects on your app.
How can I check from my Application class if theres another instance inside the Application onCreate to avoid crashes with Fabric or others?
Generally speaking, you don't "check to see" if there is another Application object from another process. You simply assume that there is always exactly one Application object created for every process in your app, and ensure for yourself that it will be safe to run in conjunction with other Applications objects in other processes. Just don't access any shared read/write resources from Application and you will be fine.
If you must initialize something from only the main process, a more reliable way of doing this is to create a ContentProvider (declare in your manifest and create an object for it like any other component), and use its onCreate(). ContentProviders are only created and initialized from the main process - never from other processes. This way you can be sure that your init will not be duplicated in any other process.
Or if you don't want to deal with this at all, just wait until Crash Reporting comes out of beta to full release, as it will not use an extra process at that time in the future. We (Google) can't say exactly when that will be, but we're not wasting any time in getting the full release published.
I have read the following statements here
By default, all components of the same application run in the same process and most applications should not change this. However, if one needs to control which process a certain component belongs to, he can do so in the manifest file. The manifest entry for each type of component element—<activity>, <service>, <receiver>, and <provider>—supports an android:process attribute that can specify a process in which that component should run. One can set this attribute so that each component runs in its own process or so that some components share a process while others do not.
I want to know in which scenarios a developer would like to do so and run different components in different processes and what advantage will he get by doing so?
Another statement that I have read is
The <application> element in the manifest file also supports an android:process attribute, to set a default value that applies to all components
Regarding the above statement I want to know Why would a developer do that, there is already one process associated with one application by default and all the components run inside that process.
Can anyone clarify these things for me as I am not getting any details on this anywhere else
thanks
Let us take the example of Google Chrome browser which has made best use of android:process attribute. Before that let us understand why multi-process architecture was considered.
Remember those age old days, when we were using co-operative multi-tasking operating system. There was one single process and applications used to run in that single process turn by turn. Problem with that architecture was, if one application misbehaves that single process dies off there by bringing entire system down.
Now a days modern operation system, run applications in their own processes. If one application misbehaves, the process hosting it dies off and does not affect rest of the system.
Same applies to the browser. If one web-page misbehaves, it brings down the entire browser there by making web-pages opened in other tabs unavailable. Hence multi-process architecture was built.
Separate processes are used for browser tabs to protect the browser application from bugs in the rendering engine. Each render process is run as an android service in separate process. This is done by using android:process tag of <service> element. Another important flag used for rendering engine process is android:isolateProcess. This flag ensures render process does not have access to the system resources like network, display and file system, there by making the browser application highly secure.
Here is the snippet of chrome's manifest file:
<service android:name="org.chromium.content.app.SandboxedProcessService0" android:permission="com.google.android.apps.chrome.permission.CHILD_SERVICE" android:exported="false" android:process=":sandboxed_process0" android:isolatedProcess="true" />
Here is the output of adb shell:
USER PID PPID VSIZE RSS WCHAN PC NAME
u0_a14 12926 317 694380 102828 ffffffff 00000000 S com.android.chrome
u0_i16 26875 317 590860 59012 ffffffff 00000000 S com.android.chrome:sandboxed_process5
u0_i17 27004 317 577460 47644 ffffffff 00000000 S com.android.chrome:sandboxed_process6
The element in the manifest file also supports an
android:process attribute, to set a default value that applies to all
components
By default the name of the application process will be the package name specified in <manifest> tag. This can be overridden by specifying the name in the android:process attribute of the <application> tag. One use case : if multiple applications want to run in the same process, provided those applications are signed by same certificate and share the user ID.
If the name of <android:process> starts with :, it becomes private to that application, as in case of chrome's rendering engine (com.android.chrome:sandboxed_process5). It implies applications except com.android.chrome cannot communicate with this rendering engine.
If the name of <android:process> starts with lowercase character, it becomes global process. From docs:
This allows components in different applications to share a process,
reducing resource usage.
Summary of benefits:
To improve overall application stability (crashes / hangs). One service process crash does not bring down entire application.
Security by preventing access to the rest of the system.
Reduce resource usage, by running component in a process and sharing it among different applications.
Basically you should be able to separate the concerns and decide whether it makes sense to apply multi-process architecture.
Update 1: Adding #Budius comment
Each process have only a certain amount of memory available. In the app I work at, we do computational intensive processing in large memory arrays. Those computational we always fire in a separate process to make sure we'll have enough memory for the whole thing to happen and not crash with OutOfMemory.
The reason one might want to do this is because Android can shut down your application process to free up memory in the system any time it wants to, and you may want to mitigate the situation.
Suppose you have a really, really important piece of code that takes a long while to complete that would be very bad to kill in the middle of it working (for instance, a financial transaction in bank software). Putting this piece of code in a Service that runs in a separate process from the rest of the application code will ensure Android doesn't kill your Service that is potentially still running after the user exited your application.
From the docs:
When deciding which processes to kill, the Android system weighs their
relative importance to the user. For example, it more readily shuts
down a process hosting activities that are no longer visible on
screen, compared to a process hosting visible activities. The decision
whether to terminate a process, therefore, depends on the state of the
components running in that process.
You can read more here
In general, a Service is used when you expect a non-UI task to take a fairly long time to complete. An Activity that does not remain in the foreground can in all probability be terminated by the OS, while a Service can continue to run indefinitely.
A Service is created in a separate process when you don't want the garbage collector to affect its working. The garbage collector will, in that case, affect only the application process. Moreover, a Service in a separate process has the added advantage that it will consume slightly less memory than what it would if it were in the main application process.
The Service that you declare in a separate process can be either private to the application:
<service android:process=":my_private_process"
or it can be global:
<service android:process="my_global_process"
In the latter case there is no colon prefix. A Service in a private process can only interact with your application, while a Service in a public process can deal with other applications as well. This is mainly when a Service should be used in a separate process: when you want your application to share data or functionality with other applications, and to do it in the background without being disturbed by the OS or the GC. To quote the documentation:
This allows components in different applications to share a process, reducing resource usage.
as far as i understand each android process runs in a "sandbox" environment, what happen if an android application is a multi process application? do all processes use the one single sandbox since all the processes use the same user id?
As Android uses the Linux kernel for sanboxing, the real sandbox is per (unix) user id, rather than per process. And the Dalvik VM itself makes no attempt at sandboxing.
Of course proccesses owned by the same user id are somewhat isolated from each other, but tools like kill(), ptrace() and the /proc filesystem which pierce process isolation are available - and governed primarily by user id isolation.
There are a couple of oddities about how code maps to processes however:
Either an Activity or a Service can be designated in the manifest to run in a distinct process, but this will still be a process owned by the package user id
Distinct application packages with the same signing certificate can use the shared user id feature to share a sandbox; in some cases this can result in their code running in the same process.
The multiprocess attribute of the <activity> tag says that the activity could run in the process of whatever starts it - it's not entirely clear if this could mean it would end up running under a foreign userid (an idea that seems more risky for the caller than the callee).
The isolatedprocess attribute of the <service> says that it runs the service in an isolated process with "no permissions of its own" - while it doesn't come out and explicitly say so, I suspect this may mean that this would be a process owned by a distinct, minimally privileged user id.
A more definitive explanation on these last two points would be good. Perhaps I'll look at the implementing code when I have more time.
Each process is associated with a separate runtime (JVM) and sandbox in Android.
For example, if you tune couple of your activities to run on a separate processes (to take advantage of having a distinct memory space) then you end up with having 2 sandboxes when you launch the app and have to manage IPC if needed.
Another example is - if you set two different apps to share the same user id then you won't need IPC since they can see each other's data, but that doesn't mean they run on the same process or sandbox. You need to set process attribute of application element in the manifest.
Out of the context, you can also have multiple components belongs to separate apps to easy sharing and saving memory.
I have an application with two Broadcast Receivers, one of them to receive data and the other one to send it. I've seen that they have an attribute android:process to make them run on the application's default process or in another one. In the examples I found using google, receivers were set to run in the process ":remote".
My question is, what are the advantages and disadvantages of using each option?
Using a different Process than the Default Process of the Application is handy when you want to share ressources with another Application.
Todo so you need to arrange two Applications with the same processname, if your processname begins with an lowerchar a global process is spawned. If it begins with a colon : than the process is private.
Keep in mind that to share a process between two apps you need the same userID and the same app certificate.
You also have to load ressources only once and get benefits in memory consumption.
for more information
A process has its own main thread. So, when using different processes i.e. :remote, then it means the code defined in that process will run on a separate thread. You don't usually need to do this for an ordinary workflow.