简体   繁体   中英

Installing an Android apk programmatically as part of a test framework

I'm attempting to install an apk programmatically, but I'm not having much luck. I'm setting up an automated test framework targeting physical devices, and I want to have the test devices retrieve the latest apk from the build server before running tests. While I am aware that there is no general way to actually install an apk without the user's consent, I'm curious if there might be some approach available in the case where a developer owns both the apk and device.

Approaches I've tried in the past (the apk has been downloaded to pathName/apkFilename):

String command = "adb install " + pathName + apkFilename;
Runtime.getRuntime().exec(command);

And:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(pathName + apkFilename)), "application/vnd.android.package-archive");
getActivity().startActivity(intent);

While I haven't been able to get the first approach to work, the second attempt creates a system dialog asking the user to confirm the installation (so almost there, but not quite). Since it is a System dialog, I, unfortunately, cannot use Robotium to confirm.

A lot of people are trying to solve similar problems. I believe it may not be possible to install an APK without confirmation, at least not easily:

I've accepted for a while now that it's impossible to silently install an application on Android

You cannot silently install app, its not supported by Android for obvious reasons. Application installation requires user intervention to continue.

Workarounds?

You need the app to have the android.permission.INSTALL_PACKAGES permission.

There are some hints on those threads about how to do this if you have certain priveleges, though it might be hard to get your app to run that way. You might have to install to a special directory, and/or you might have to run as a special user (which might be hard to do).

One possible way to run the app with elevated permissions: How can I get root permissions through the Android SDK?

On this thread, they mention you might have to "root" your phone to enable that permission:

I wouldn't be surprised if this voids the warranty though. You mentioned in the comments on your post that you don't have "control over the device", so that might kill this option too.

There is some mention on this thread of exploits that some apps use , but I don't think they're supported. If they still work, they might stop working at some point.

I'm trying to do the same thing, in order to push updates to devices we control. In our case they're already rooted, and the application has been granted superuser, so I think just copying the .apk over the top of the existing file would probably work, but this seems very hacky.

What seems like a better approach (if it works) is to use the pm Package Manager application:

# /system/bin/pm
usage: pm [list|path|install|uninstall]
       pm list packages [-f]
       pm list permission-groups
       pm list permissions [-g] [-f] [-d] [-u] [GROUP]
       pm list instrumentation [-f] [TARGET-PACKAGE]
       pm list features
       pm path PACKAGE
       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH
       pm uninstall [-k] PACKAGE
       pm enable PACKAGE_OR_COMPONENT
       pm disable PACKAGE_OR_COMPONENT
       pm setInstallLocation [0/auto] [1/internal] [2/external]

The list packages command prints all packages.  Options:
  -f: see their associated file.

The list permission-groups command prints all known
permission groups.

The list permissions command prints all known
permissions, optionally only those in GROUP.  Options:
  -g: organize by group.
  -f: print all information.
  -s: short summary.
  -d: only list dangerous permissions.
  -u: list only the permissions users will see.

The list instrumentation command prints all instrumentations,
or only those that target a specified package.  Options:
  -f: see their associated file.

The list features command prints all features of the system.

The path command prints the path to the .apk of a package.

The install command installs a package to the system.  Options:
      -l: install the package with FORWARD_LOCK.
  -r: reinstall an exisiting app, keeping its data.
  -t: allow test .apks to be installed.
  -i: specify the installer package name.
  -s: install package on sdcard.
  -f: install package on internal flash.

The uninstall command removes a package from the system. Options:
  -k: keep the data and cache directories around.
after the package removal.

The enable and disable commands change the enabled state of
a given package or component (written as "package/class").

The getInstallLocation command gets the current install location
  0 [auto]: Let system decide the best location
  1 [internal]: Install on internal device storage
  2 [external]: Install on external media

The setInstallLocation command changes the default install location
  0 [auto]: Let system decide the best location
  1 [internal]: Install on internal device storage
  2 [external]: Install on external media

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM