What Is Shareduserid in Android, and How Is It Used

What is sharedUserId in Android, and how is it used?

SharedUserId is used to share the data,processes etc between two or more applications.
It is defined in AndroidManifest.xml like,

<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="android.uid.shared"
android:sharedUserLabel="@string/sharedUserLabel"
...>

and define the shared parameter in Android.mk for that app, like

LOCAL_CERTIFICATE := shared

Hope its helpful to you.

Two app with shared UserID

You can use android:sharedUserId in AndroidManifest.xml to let your application share the same user id with another application.

android:sharedUserId

The name of a Linux user ID that will be shared with other
applications. By default, Android assigns each application its own
unique user ID. However, if this attribute is set to the same value
for two or more applications, they will all share the same ID —
provided that they are also signed by the same certificate.
Application with the same user ID can access each other's data and, if
desired, run in the same process.

Notice that they need to be signed by the same certificate.

Two applications share the same user id may access each other's resource.

For example:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.shareusertesta"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="com.example">

Then we can init a new context of com.example by:

Context friendContext = this.createPackageContext( "com.example",Context.CONTEXT_IGNORE_SECURITY);

And access some resources of that application:

friendContext.getResources().getString(id);
friendContext.getResources().getDrawable(id);
friendContext.registerReceiver(...);

android:sharedUserId= android.uid.system Obtaining Files from SDCard

A system app can't read from external storage? That's news to me, but anyway.

You can always just create a pipe and pass the read end back over the IPC mechanism of your choice (ContentProvider.call() for example). The service-side starts a thread and writes the file to the write end, and passes the read end back to the client. Something like this on the service side:

  ParcelFileDescriptor[] fds;
try {
fds = ParcelFileDescriptor.createPipe();
} catch (IOException e) {
e.printStackTrace();
return false;
}

final ParcelFileDescriptor readFd = fds[0];
final ParcelFileDescriptor writeFd = fds[1];

// TODO: start a thread to write file to writeFd

Bundle result = new Bundle();
extras.putParcelable(EXTRA_READ_FD, readFd);

return result; // Return from call() to client

Obviously there is a lot of boilerplate code left as an exercise for the reader.

security in using shareduserid

Shared user IDs are enforced by the certificate signature. The platform will grant/assign same user ID only if the applications are signed with the same certificate. Ref.:

android:sharedUserId

The name of a Linux user ID that will be shared with other applications. By default, Android assigns each application its own unique user ID. However, if this attribute is set to the same value for two or more applications, they will all share the same ID — provided that they are also signed by the same certificate. Application with the same user ID can access each other's data and, if desired, run in the same process.

Content Provider vs SharedUserId vs Global Process for sharing data across applications

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.

sharedUserId: safe to change when app is already in market?

And to answer my own question again:

No, it's not safe. Since updating an app via Android Market will not remove the database and preference files, the new version will not be able to read or write these files (since they were created under a different Linux user ID), and the app will crash after the update. You would have to ask your users to completely uninstall and reinstall the app, which is certainly not recommended.

As a general rule I conclude from this:
Whenever you start out developing a new app, make sure to set a manual android:process and android:sharedUserId attribute! It doesn't hurt in case you don't need it, but it gives you full control over which apps have access to this app's private resources.

SharedUserId & Files

Can sharedUserId provide access to files in the data/data/com.example/files dir?

Yes, if and only if:

  • Both apps have the same non-empty sharedUserId value

  • Both apps have always had the same non-empty sharedUserID value (i.e., you cannot update an app from not having sharedUserId to having a sharedUserId)

  • Both apps are signed by the same signing key

That being said, sharedUserId is almost never the right answer, for the simple reason that neither app will know about what the other app is doing with the files. Use a ContentProvider (or some other form of IPC) to share content between apps, using signature-level permissions or other identity checks to ensure that only the right apps can interact over the IPC channel.



Related Topics



Leave a reply



Submit