我们可以从ContentProvider安装APK吗?

Com*_*are 43 android

我正在开发一个库,允许应用程序自行更新,以便在Android Market之外分发.

我最初的计划是包含将APK文件下载到内部存储的代码,然后通过a ContentProvider和a 安装它content:// Uri.但是,当我尝试这样做时,安装程​​序系统向LogCat转储了一个"Skipping dir:"警告,但未能实际安装它.有一次,我切换到下载APK到外部存储和使用file:// UriACTION_VIEW安装程序Intent,它的工作.

在"跳过目录"的消息似乎被记录parsePackage()PackageParser,这似乎认为它正在与一个File.这表明我们不能使用content:// Uri价值观.

有没有人成功地使用ACTION_VIEWapplication/vnd.android.package-archive Intentcontent:// Uri?如果是这样,是否有一些特定的技巧来设置ContentProvider它使它工作?

谢谢!

Al *_*ton 27

ACTION_INSTALL_PACKAGE的文档不正确.它也只接受文件.

因此,我唯一的建议是在应用程序文件区域中创建该文件的副本,使其具有全局可读性,并在以后清理任何遗留文件.

以前的错误答案:在4.0及以上版本中有一个ACTION_INSTALL_PACKAGE,它将接受content:// URI(JavaDoc),但在此之前,您只能通过ACTION_VIEW进行安装,它假设传递的URI是一个文件://URI.

  • 注意:`content`方案适用于Android 7.0,但不适用于以前版本的Android. (3认同)
  • 我对文档很有信心,但看起来文档错了.服务ACTION_INSTALL_PACKAGE的代码也只接受文件.是时候注册一个bug了.抱歉. (2认同)

Jul*_*les 14

我认为这是不可能的,因为Java API似乎不允许它.ContentProvider openFile()返回a ParcelFileDescriptor,您可以从中获取java.io.FileDescriptor.然后,您可以使用它FileDescriptor打开a FileInputStream或a FileOutputStream.不幸的是,你不能用它来打开一个RandomAccessFile(尽管RandomAccessFile对描述符起作用的事实和其他描述符一样,你需要的构造函数只是在API中丢失).

由于APK文件是ZIP文件,必须按顺序读取(你必须寻找最终才能找到文件目录),我认为安装的实现需要一个RandomAccessFile,所以不可能支持这个案例你正试图实施.


njz*_*zk2 6

我同意Jules的分析,并且我会添加具体的精确度:

PackageInstallerActivity,由apk上的ACTION_VIEW调用,在onCreate()方法中有这个:

315 String apkPath = mPackageURI.getPath();
316 File apkFile = new File(apkPath);
Run Code Online (Sandbox Code Playgroud)

在此之前,此方法PackageUtil称为:

73 public static  PackageParser.Package getPackageInfo(Uri packageURI) {
74     final String archiveFilePath = packageURI.getPath();
75     PackageParser packageParser = new PackageParser(archiveFilePath);
76     File sourceFile = new File(archiveFilePath);
77     DisplayMetrics metrics = new DisplayMetrics();
78     metrics.setToDefaults();
79     return packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
80 }
Run Code Online (Sandbox Code Playgroud)

所有这些都倾向于确认PackageManager确实只需要File Uris.

Skipping dir:找到您所拥有的日志,该日志packageParser.parsePackage测试Uri中给出​​的路径是否为文件.