'Is it possible to send Uri using AIDL?
I have two apps, lets say AppClient and AppService. Those apps are communicating between each other using AIDL methods. Right now I would like to send Uri from AppClient to AppService in AIDL method parameter. I can send it without any problems but when I trying to open stream to read file using
context.contentResolver.openInputStream(uriFile)
I'm getting SecurityException. Permission Denial: opening provider androidx.core.content.FileProvider from ProcessRecord{94e65ad 6186:com.app.service/u0a231} (pid=6186, uid=10231) that is not exported from uid 10043
In AppClient before sending Uri via AIDL method I'm granting required permissions first.
val uri = FileProvider.getUriForFile(this,"com.app.client.fileprovider", fontFile)
grantUriPermission("com.app.service", uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION and Intent.FLAG_GRANT_READ_URI_PERMISSION)
In documentation is see thet Uri is transported to other app using Intents but it I don't want to use Intents. It is possible to send Uri not using Intent e.g. in AIDL parameter ?
Solution 1:[1]
you need to create a wrapper over Uri to remotely open a Uri through AIDL. I do this in send Uri from the main profile to the work profile in Android.
look at Shelter open source project on Github for details. UriForwardProxy
// A wrapper over Uri to remotely open an Uri through AIDL
// This is used to forward Content URIs through the profile
// boundary.
public class UriForwardProxy implements Parcelable {
public static final Parcelable.Creator<UriForwardProxy> CREATOR = new Parcelable.Creator<UriForwardProxy>() {
@Override
public UriForwardProxy[] newArray(int size) {
return new UriForwardProxy[0];
}
@Override
public UriForwardProxy createFromParcel(Parcel source) {
IBinder[] arr = new IBinder[1];
source.readBinderArray(arr);
IUriOpener opener = IUriOpener.Stub.asInterface(arr[0]);
return new UriForwardProxy(opener);
}
};
private IUriOpener mOpener;
private UriForwardProxy(IUriOpener opener) {
mOpener = opener;
}
public UriForwardProxy(Context context, Uri uri) {
ContentResolver resolver = context.getContentResolver();
mOpener = new IUriOpener.Stub() {
@Override
public ParcelFileDescriptor openFile(String mode) {
try {
return resolver.openFileDescriptor(uri, mode);
} catch (FileNotFoundException e) {
return null;
}
}
};
}
public ParcelFileDescriptor open(String mode) {
try {
return mOpener.openFile(mode);
} catch (RemoteException e) {
return null;
}
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeBinderArray(new IBinder[]{mOpener.asBinder()});
}
@Override
public int describeContents() {
return 0;
}
}
Solution 2:[2]
grantUriPermission("com.app.service", uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Golil |
Solution 2 | procrastinator |