如何向设置android:isolatedProcess的Android Service传递PDF文件生成缩略图
在Android隔离进程Service中传递不可信PDF文件的问题
我需要在设置了isolatedProcess = true的Android Service中,为来自不可信来源的PDF文件生成缩略图。这么做是因为不可信文件存在安全风险,Android PdfRenderer文档也明确建议:
如果文件来自不可信来源,建议在独立的隔离进程中运行渲染器,并赋予最小权限,以此限制安全漏洞的影响范围。
但现在遇到了文件传递的难题:
- 若通过Intent以byteArray形式传递文档,会触发
TransactionTooLargeException; - 若传递文件URI并尝试用ContentResolver打开InputStream,会抛出隔离进程无权访问ContentResolver的异常。
更新:附上关键代码片段
Android Manifest
<application> ... <service android:name=".util.thumbnail.ThumbnailCreationService" android:isolatedProcess="true" android:exported="false" android:process=":remote" /> </application>
Activity通过Message Handler向Service发送数据
class MainActivity : Activity { ... /** * Class for interacting with the main interface of the service. */ private val mConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected( className: ComponentName, service: IBinder ) { mService = Messenger(service) registerClient(mMessenger) } override fun onServiceDisconnected(className: ComponentName) { mService = null unregisterClient(mMessenger) Timber.d("Service disconnected") } } fun sendMessageToService(fileUri: Uri){ mService?.let { val msg = Message.obtain( null, MSG_CREATE_THUMBNAIL, this.hashCode(), 0 ) val bundle = Bundle() // 向Service发送文档URI bundle.putString(ARG_DOCUMENT_DATA_URI, fileUri.toString()) // 若传递文档数据会触发TransactionTooLargeException // bundle.putByteArray(ARG_DOCUMENT_DATA, document) bundle.putString(ARG_DOCUMENT_MIME_TYPE, mimeType) msg.data = bundle it.send(msg) } }
Service: ThumbnailCreationService
class ThumbnailCreationService : Service() { var mClients = ArrayList<Messenger>() /** * 处理来自客户端的消息 */ internal class IncomingHandler(private val thumbnailCreationService: ThumbnailCreationService) : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { Timber.d("Retrieved client message: ${msg.what}") when (msg.what) { MSG_CREATE_THUMBNAIL -> { msg.data?.let { val uri = Uri.parse(it.getString(ARG_DOCUMENT_DATA_URI)) thumbnailCreationService.loadDocumentData(uri) } } else -> super.handleMessage(msg) } } } protected fun loadDocumentData(uri: Uri) = // 此处contentResolver会崩溃,因为隔离进程无权访问ContentResolver this.contentResolver.openInputStream(uri)?.use { IOHandler.readFileUriContent(it) } }
堆栈信息
java.lang.SecurityException: Isolated process not allowed to call getContentProvider at android.os.Parcel.createExceptionOrNull(Parcel.java:3011) at android.os.Parcel.createException(Parcel.java:2995) at android.os.Parcel.readException(Parcel.java:2978) at android.os.Parcel.readException(Parcel.java:2920) at android.app.IActivityManager$Stub$Proxy.getContentProvider(IActivityManager.java:5224) at android.app.ActivityThread.acquireProvider(ActivityThread.java:7019) at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:3420) at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:2526) at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:2011) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1842) at android.content.ContentResolver.openInputStream(ContentResolver.java:1518)
内容的提问来源于stack exchange,提问作者Snake
相关产品推荐
相关产品推荐

