我的应用程序会安装其他应用程序,它需要跟踪安装了哪些应用程序.当然,这可以通过简单地保存已安装应用程序的列表来实现.但这不应该是必要的!包装经理应负责维护installedBy(a,b)关系.事实上,根据API,它是:

公共抽象字符串getInstallerPackageName(字符串packageName)-

当前的做法

使用Intent安装APK

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(intent);

使用Intent卸载APK:

Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package",
getPackageManager().getPackageArchiveInfo(apkUri.getPath(), 0).packageName,null));
startActivity(intent);

这显然不是Android Market安装/卸载软件包的方式.他们使用更丰富版本的PackageManager.这可以通过从Android Git存储库下载Android源代码来看到.下面是与意图方法相对应的两个隐藏方法.不幸的是,它们对外部开发人员不可用.但也许他们会在future 呢?

更好的方法

使用PackageManager安装APK

/**
 * @hide
 * 
 * Install a package. Since this may take a little while, the result will
 * be posted back to the given observer.  An installation will fail if the calling context
 * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
 * package named in the package file's manifest is already installed, or if there's no space
 * available on the device.
 *
 * @param packageURI The location of the package file to install.  This can be a 'file:' or a
 * 'content:' URI.
 * @param observer An observer callback to get notified when the package installation is
 * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
 * called when that happens.  observer may be null to indicate that no callback is desired.
 * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
 * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
 * @param installerPackageName Optional package name of the application that is performing the
 * installation. This identifies which market the package came from.
 */
public abstract void installPackage(
        Uri packageURI, IPackageInstallObserver observer, int flags,
        String installerPackageName);

使用PackageManager卸载APK

/**
 * Attempts to delete a package.  Since this may take a little while, the result will
 * be posted back to the given observer.  A deletion will fail if the calling context
 * lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the
 * named package cannot be found, or if the named package is a "system package".
 * (TODO: include pointer to documentation on "system packages")
 *
 * @param packageName The name of the package to delete
 * @param observer An observer callback to get notified when the package deletion is
 * complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
 * called when that happens.  observer may be null to indicate that no callback is desired.
 * @param flags - possible values: {@link #DONT_DELETE_DATA}
 *
 * @hide
 */
public abstract void deletePackage(
        String packageName, IPackageDeleteObserver observer, int flags);

差异

  • 使用Intents时,本地包管理器不知道安装来自哪个应用程序.具体地说,getInsteller PackageName(.)返回NULL.

  • 隐藏方法installPackage(…)将安装程序包名称作为参数,并且很可能能够设置此值.

问题

是否可以使用intents指定软件包安装程序名称

提示:如果你想下载Android源代码,你可以按照这里描述的步骤:下载源代码树.提取*.java文件,并根据包的层次 struct 将它们放在文件夹中,您可以查看以下整洁的脚本:View Android Source Code in Eclipse我>

推荐答案

这是目前第三方应用程序无法使用的.请注意,即使使用反射或其他技巧来访问installPackage(),也无济于事,因为只有系统应用程序才能使用它.(这是因为它是在用户批准权限后的低级安装机制,因此常规应用程序访问它是不安全的.)

此外,installPackage()函数参数在不同的平台版本之间经常会发生变化,因此您try 访问它的任何操作都会在平台的其他各种版本上失败.

编辑:

另外值得指出的是,这个installerPackage是最近才添加到平台上的(2.2?)它最初并不是用于跟踪谁安装了应用程序——平台使用它来确定在报告应用程序错误时由谁启动,以实现Android反馈.(这也是API方法参数更改的次数之一.)在推出之后的至少很长一段时间里,Market仍然没有使用它来跟踪它安装的应用程序(而且它很可能仍然没有使用它),而是使用它将Android反馈应用程序(与Market分离)设置为"所有者"来处理反馈.

Android相关问答推荐

如何使用喷气背包压缩让Animated Image Vector每次动画化一条路径?

Kotlin多平台向导,不兼容版本(ANP 8.2.0)ANP 8.1.2

无法安装后重新编译android代码'

如何将子零部件的大小调整为可以调整大小的父组件大小?

尽管我们不再使用GCM SDK,但应用程序已被标记为使用GCM SDK

从片段导航回来

Jetpack Compose 使用 SavedStateHandle 发送返回结果不适用于 ViewModel 中注入的 SavedStateHandle

kotlin中&&和and的区别

如何在 Delphi 和 Android 上避免 Indy Socket Error #13 Access denied 异常?

视觉转换后获取文本

获取 ArithmeticException:除以零,但我没有在任何地方除以零

在 Jetpack Compose 中包装内容

PullRefreshIndicator 与 ScrollableTabRow 重叠

如何只允许拖动 BottomSheetScaffold 中 BottomContent 的 SheetPeek 的一部分?

如何在屏幕旋转或系统主题更改后将光标移动到 TextField 的末尾并保持键盘显示?

记住或不记得derivedStateOf

更新后 Firebase 服务无法在模拟器上运行

在 jetpack compose 中使用 viewmodel 的最佳实践

Jetpack Compose Material3 - switch 标签

CenterAlignedTopAppBar 滚动行为:未为参数状态传递值