以授权的INSTALL_PACKAGES权限静默安装应用程序

POM*_*ATu 84 android install silent

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

但是我找不到任何地方如何使用此权限.我试图将文件复制到/ data/app并没有成功.我也试过使用这段代码

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

但是此代码打开标准安装对话框.如何在没有root的情况下以静默方式安装app android.permission.INSTALL_PACKAGES

PS我正在编写一个应用程序,它会在第一次启动时将许多来自文件夹的apks安装到系统中(替换安装向导).我需要它来使固件更轻.

如果您认为我正在编写病毒:所有程序都安装在/ 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

ina*_*ruk 60

你的第一个赌注是研究Android的原生PackageInstaller.我建议您按照自己喜欢的方式修改该应用,或者只是提取所需的功能.


具体来说,如果您查看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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你会注意到实际的安装程序位于InstallAppProgress类中.检查该类你会发现initView是核心安装程序的功能,它的最后一件事是调用PackageManagerinstallPackage函数:

public void initView() {
...
pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
}
Run Code Online (Sandbox Code Playgroud)

下一步是检查PackageManager,它是抽象类.你会在installPackage(...)那里找到功能.坏消息是它标有@hide.这意味着它不能直接使用(您将无法通过调用此方法进行编译).

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

但是你可以通过反射访问这些方法.

如果你有兴趣在如何PackageManagerinstallPackage功能实现,看看PackageManagerService.

摘要

你需要通过Context' 获取包管理器对象getPackageManager().然后你将installPackage通过反射调用函数.

  • 您的应用请求该权限,但Android不会将此权限授予第三方应用.请参阅"LogCat"以获取与权限相关的日志. (12认同)
  • 答案中的所有链接均无效。 (4认同)
  • 如何通过反射调用installPackage?实际上我不能做Method method = aPackageManagerClass.getMethod("installPackage",new Class [] {Uri.class,IPackageInstallObserver.class,Integer.TYPE,String.class}); 鉴于IPackageInstallObserver也是隐藏的,有人可以帮我打趣,发布正确的代码来做反思. (3认同)
  • 救命!此技术导致:由以下原因引起:java.lang.SecurityException:用户10101和当前进程都没有android.permission.INSTALL_PACKAGES.即使我的应用程序具有该权限 (2认同)

Fra*_*eNL 13

我已经检查了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),它应该安装另一个应用程序.
(正常安装,非root设备)
它确实:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
但是这给出了错误:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
似乎错误是由pm引发的,而不是由AppInstall引发的.
因为AppInstall没有捕获SecurityException,并且应用程序不会崩溃.

我在root设备(同样的应用程序和AppInstall)上尝试过相同的东西,它就像一个魅力.
(也正常安装,不在/ system或任何东西)
AppInstall甚至没有询问root权限.
但那是因为shell总是#代替$那个设备.

顺便说一句,你需要root才能在/ system中安装应用程序,对吗?
我在非root用户设备上尝试了adb remount并获得:
remount failed: Operation not permitted.
这就是为什么我无法在非root设备上尝试/ system的原因.

结论:你应该使用root设备
希望这有助于:)


Bor*_*hov 10

我最近在没有用户同意的情况下实施了安装 - 它是API级别21+的自助服务终端应用程序,我可以完全控制环境.

基本要求是

  • API等级21+
  • root访问权限将updater安装为系统特权应用程序.

以下方法从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;
    }
Run Code Online (Sandbox Code Playgroud)

以下代码调用安装

 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();
     }
Run Code Online (Sandbox Code Playgroud)

为了整个工作你迫切需要INSTALL_PACKAGES许可,否则上面的代码将无声地失败

<uses-permission
        android:name="android.permission.INSTALL_PACKAGES" />
Run Code Online (Sandbox Code Playgroud)

要获得此权限,您必须将您的APK安装为需要root的系统应用程序(但是,在您安装了更新程序应用程序之后,它似乎在没有root的情况下工作)

要安装为系统应用程序,我创建了一个签名的APK并推送它

adb push updater.apk /sdcard/updater.apk
Run Code Online (Sandbox Code Playgroud)

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

adb shell
su
mount -o rw,remount /system
mv /sdcard/updater.apk /system/priv-app
chmod 644 /system/priv-app/updater.apk
Run Code Online (Sandbox Code Playgroud)

由于某种原因,它不适用于简单的调试版本,但如果您的应用程序因某些原因未被选中,则logcat会显示有用的信息priv-app.


小智 8

你应该定义

<uses-permission
    android:name="android.permission.INSTALL_PACKAGES" />
Run Code Online (Sandbox Code Playgroud)

在您的清单中,如果您是在系统分区(/ system/app)中还是由制造商签署了您的应用程序,您将获得INSTALL_PACKAGES权限.

我的建议是创建一个具有1.5兼容级别的小型android项目,用于通过反射调用installPackages并导出jar,其方法是安装包并调用实际方法.然后,通过在项目中导入jar,您就可以安装包了.


Vla*_*mir 5

我试过扎根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();
        }
     }
}
Run Code Online (Sandbox Code Playgroud)

  • 问题是关于安装没有root的应用程序,但具有系统"INSTALL_PACKAGES"权限.我在你的回答中看到"su",所以它需要root. (2认同)