默认安装应用程序,授予INSTALL_PACKAGES权限

我试图默默安装apk到系统中。 我的应用程序位于/系统/应用程序,并成功授予“android.permission.INSTALL_PACKAGES”权限

但是,我无法find任何地方如何使用此权限。 我试图复制文件到/数据/应用程序,并没有成功。 此外,我尝试使用此代码

Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType( Uri.parse("file:///sdcard/app.apk"), "application/vnd.android.package-archive"); startActivity(intent); 

但是这个代码打开标准安装对话框。 如何在没有授予android.permission.INSTALL_PACKAGES情况下以默认方式安装应用程序?

PS我正在写一个应用程序,将在第一次启动时从文件夹安装许多apks到系统(replace安装向导)。 我需要它来使固件更轻。

如果您认为我正在编写病毒:所有程序都安装到/ data / app中。 权限Install_packages只能授予位于/ system / app中的系统级程序或使用系统密钥签名。 所以病毒无法到达那里。

正如所说的http://www.mail-archive.com/android-porting@googlegroups.com/msg06281.html应用程序可以无提示安装,如果他们有install_packages权限。 此外,您不需要Install_packages权限就可以不安静地安装软件包。 加上http://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html

你的第一个select是查看Android的本地PackageInstaller 。 我会build议您修改该应用程序的方式,或者只是提取所需的function。


具体而言,如果您查看PackageInstallerActivity及其onClickListener方法:

  public void onClick(View v) { if(v == mOk) { // Start subactivity to actually install the application Intent newIntent = new Intent(); ... newIntent.setClass(this, InstallAppProgress.class); ... startActivity(newIntent); finish(); } else if(v == mCancel) { // Cancel and finish finish(); } } 

然后你会注意到实际的安装程序位于InstallAppProgress类中。 检查这个类,你会发现initView是核心安装程序的function,最后它是调用PackageManagerinstallPackage函数:

 public void initView() { ... pm.installPackage(mPackageURI, observer, installFlags, installerPackageName); } 

下一步是检查PackageManager ,它是抽象类。 你会在installPackage(...)findinstallPackage(...)函数。 坏消息是它用@hide标记。 这意味着它不是直接可用的(您将无法通过调用此方法进行编译)。

  /** * @hide * .... */ public abstract void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,String installerPackageName); 

但是你可以通过reflection来访问这个方法。

如果您对PackageManagerinstallPackage函数的实现感兴趣,请查看PackageManagerService 。

概要

你需要通过ContextgetPackageManager()来获得包pipe理器对象。 然后你会通过reflection调用installPackage函数。

我已经检查过ADB如何安装应用程序。
– 它将APK复制到/ data / local / tmp
– 它运行'shell:pm install /data/local/tmp/app.apk'

我试图通过这样做来复制这个行为:(在pc上,使用usb-cable)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
这工作。 该应用程序已安装。

我做了一个应用程序(名为AppInstall),它应该安装其他应用程序。
(正常安装,无根设备)
它确实:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
但是这给了错误:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
这似乎是错误是由下午,而不是由AppInstall抛出。
因为AppInstall没有捕获SecurityException,应用程序不会崩溃。

我已经尝试了一个根植设备(相同的应用程序和AppInstall)同样的事情,它的工作就像一个魅力。
(也正常安装,不在/系统或任何东西)
AppInstall甚至没有问根权限。
但是,这是因为shell在该设备上总是#而不是$

顺便说一句,你需要root安装在/系统中的应用程序,正确的?
我尝试adb重新安装在没有根的设备上,得到:
remount failed: Operation not permitted.
这就是为什么我不能在非根设备上尝试/系统的东西。

结论:你应该使用一个根植的设备
希望这可以帮助 :)

你应该定义

 <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 

在你的清单中,如果你是在系统分区(/ system / app)中,或者你有你的应用程序由制造商签名,你将有INSTALL_PACKAGES权限。

我的build议是创build一个具有1.5兼容性级别的小型Android项目,用于通过reflection调用installPackages,并导出包含安装包的方法和调用真实方法的jar。 然后,通过将jar导入到您的项目中,您将准备好安装软件包。

我不知道该怎么做,因为没有人回答这个问题,而且我也没有发现有关这个许可的文件。 所以我find了自己的解决scheme。 你的身体比较好,但这是一个解决办法。

我安装了busybox,设置777权限/ data / app(我不关心安全性)。 然后刚从应用程序执行“busybox安装”。 这工作,但有一个很大的安全漏洞。 如果您设置权限777,则不需要root用户。

这是一个非常好的post在这个问题上。 它帮了我很多。

您可以简单地使用adb install命令来静默安装/更新APK。 示例代码如下

 public static void InstallAPK(String filename){ File file = new File(filename); if(file.exists()){ try { String command; filename = StringUtil.insertEscape(filename); command = "adb install -r " + filename; Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }); proc.waitFor(); } catch (Exception e) { e.printStackTrace(); } } } 

我尝试了扎根的Android 4.2.2,这种方法适用于我:

 private void installApk(String filename) { File file = new File(filename); if(file.exists()){ try { final String command = "pm install -r " + file.getAbsolutePath(); Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }); proc.waitFor(); } catch (Exception e) { e.printStackTrace(); } } } 

您可以通过reflection使用隐藏的API android.content.pm.IPackageInstallObserver

 public class PackageManagement { public static final int INSTALL_REPLACE_EXISTING = 0x00000002; public static final int INSTALL_SUCCEEDED = 1; private static Method installPackageMethod; private static Method deletePackageMethod; static { try { installPackageMethod = PackageManager.class.getMethod("installPackage", Uri.class, IPackageInstallObserver.class, Integer.TYPE, String.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public static void installPackage(PackageManager pm, Uri mPackageUri, IPackageInstallObserver observer, int installFlags, String installerPackageName) { try { installPackageMethod.invoke(pm, mPackageUri, observer, installFlags, installerPackageName); } catch (Exception e) { e.printStackTrace(); } } } 

android.content.pm.IPackageInstallObserver导入到您的项目中。 你的应用程序必须是系统。 您必须在清单文件中激活权限android.permission.INSTALL_PACKAGES

我最近一直在没有用户同意的情况下实施安装 – 这是一个API级21+的自助terminal应用程序,我可以完全控制环境。

基本要求是

  • API等级21+
  • root访问权限来将更新程序安装为系统特权应用程序。

以下方法从InputStream读取并安装APK:

 public static boolean installPackage(Context context, InputStream in, String packageName) throws IOException { PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); params.setAppPackageName(packageName); // set params int sessionId = packageInstaller.createSession(params); PackageInstaller.Session session = packageInstaller.openSession(sessionId); OutputStream out = session.openWrite("COSU", 0, -1); byte[] buffer = new byte[65536]; int c; while ((c = in.read(buffer)) != -1) { out.write(buffer, 0, c); } session.fsync(out); in.close(); out.close(); Intent intent = new Intent(context, MainActivity.class); intent.putExtra("info", "somedata"); // for extra data if needed.. Random generator = new Random(); PendingIntent i = PendingIntent.getActivity(context, generator.nextInt(), intent,PendingIntent.FLAG_UPDATE_CURRENT); session.commit(i.getIntentSender()); return true; } 

以下代码调用安装

  try { InputStream is = getResources().openRawResource(R.raw.someapk_source); installPackage(MainActivity.this, is, "com.example.apk"); } catch (IOException e) { Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show(); } 

对于整个工作你拼命需要INSTALL_PACKAGES权限,否则上面的代码将失败默默

 <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 

要获得这个权限,你必须安装你的APK作为系统应用程序,它需要root (但是,当你已经安装了你的更新应用程序,它似乎没有根工作)

要作为系统应用程序安装,我创build了一个签名的APK,并将其推送

 adb push updater.apk /sdcard/updater.apk 

然后将其移至system/priv-app – 这需要重新安装FS(这就是为什么需要root)

 adb shell su mount -o rw,remount /system mv /sdcard/updater.apk /system/priv-app chmod 644 /system/priv-app/updater.apk 

由于某种原因,它不适用于简单的debugging版本,但是如果您的应用程序在priv-app由于某种原因未被拾取, logcat将显示有用的信息。

我使用PackageManager.installPackage方法为静默安装制作了一个testing应用程序。

我通过reflection得到了installPackage方法,并在我的src文件夹中制作了android.content.pm.IPackageInstallObserver接口(因为它隐藏在android.content.pm包中)。

当我运行installPackage时,我得到SecurityException和string指示,我的应用程序没有android.permission.INSTALL_PACKAGES,但它在AndroidManifest.xml中定义。

所以,我认为,这是不可能的。

PS。 我在Android SDK 2.3和4.0上进行了testing。 也许它会适用于早期版本。

在pm安装之前试试这个LD_LIBRARY_PATH=/vendor/lib:/system/lib 。 它运作良好。

!/斌/庆典

 f=/home/cox/myapp.apk #or $1 if input from terminal. #backup env var backup=$LD_LIBRARY_PATH LD_LIBRARY_PATH=/vendor/lib:/system/lib myTemp=/sdcard/temp.apk adb push $f $myTemp adb shell pm install -r $myTemp #restore env var LD_LIBRARY_PATH=$backup 

这对我有用。 我运行在Ubuntuterminal上的Ubuntu 12.04。