我在Android(SDK 19 / KitKat 4.4.2)中有一个场景,其中我的应用程序将使用android:sharedUserId =“ android.uid.s作为系统级应用程序( App 1 )进行签名.system”。这意味着该应用程序无法从SD卡进行写入或读取,无论它们是外部的还是内置在设备中的。
如果我需要从SDCard获取大文件并将其读入应用程序,什么是最好的方法?
我的目标仅仅是从SDCard获取图像文件。但是,即使图像是未压缩的位图,也可能相对较大。
我尝试了以下方法:
创建一个未以系统用户身份签名的新应用程序( App2 )。从 App1 启动此 App2 中存在的服务,然后从此处从SD卡读取文件,然后获取文件的字节[],然后将其发送通过AIDL批量访问 App1 。这可以从SDCard读取文件并将其发送出去,但是AIDL每笔交易的上限为1mb,而且还很慢,我应该限制允许提供给应用程序的图像大小使此功能可用。我认为这不是最理想的。
我已经尝试在 App 2(UID:10007)中使用FileProvider,但是在这种情况下,我无需打开任何图形界面即可选择所需的文件和目标应用程序。我需要立即将其发送到 App 1(UID:10047),或立即从 App1 获取。我不确定如果没有这些gui步骤,是否可以使用FileProvider。我尝试仅通过 App2 创建Uri,然后通过AIDL将Uri发送到 App1 ,然后通过context.grantUriPermissions(packageName,uri,READ / WRITE)授予权限,但始终最终出现安全错误,其中 App1 没有读取 App2 提供的uri的权限。
java.lang.SecurityException:未为UID 10047和Uri content://com.test.sdcard/folder/img.png
授予权限其中UID 10047是应用1 ,而UID 10007是应用2 。
有其他解决方案吗?
答案 0 :(得分:1)
系统应用无法从外部存储读取?这对我来说是个新闻,但是无论如何。
您始终可以仅创建管道并将读取端传递回您选择的IPC机制(例如ContentProvider.call()
)。服务端启动线程并将文件写入写端,然后将读端传递回客户端。在服务端这样的事情:
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
很显然,还有很多样板代码可供读者练习。