[ASUS ZenFone 8] bnsmb:
How to install packages (apk files) for Android via script

Sometimes, for example after a reinstallation of the phone from scratch, it's quite useful to install all the apps via an script.

The command on Android to do that is

pm install [apk_file]

But unfortunately that does not work, neither as user shell (due to missing file access rights) nor as user root:

ASUS_I006D:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
ASUS_I006D:/ #
ASUS_I006D:/ # pm install /sdcard/Download/EssentialApps/MiXplorer_v6.58.4-API29_B22020920.apk
avc: denied { read } for scontext=u:r:system_server:s0 tcontext=u:object_r:fuse:s0 tclass=file permissive=0
System server has no access to read file context u:object_r:fuse:s0 (from path /sdcard/Download/EssentialApps/MiXplorer_v6.58.4-API29_B22020920.apk, context u:r:system_server:s0)
Error: Unable to open file: /sdcard/Download/EssentialApps/MiXplorer_v6.58.4-API29_B22020920.apk
Consider using a file under /data/local/tmp/
Error: Can't open file: /sdcard/Download/EssentialApps/MiXplorer_v6.58.4-API29_B22020920.apk

Exception occurred while executing 'install':
java.lang.IllegalArgumentException: Error: Can't open file: /sdcard/Download/EssentialApps/MiXplorer_v6.58.4-API29_B22020920.apk
at com.android.server.pm.PackageManagerShellCommand.setParamsSize(PackageManagerShellCommand.java:572)
at com.android.server.pm.PackageManagerShellCommand.doRunInstall(PackageManagerShellCommand.java:1337)
at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:1303)
at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:193)
at com.android.modules.utils.BasicShellCommandHandler.exec(BasicShellCommandHandler.java:97)
at android.os.ShellCommand.exec(ShellCommand.java:38)
at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:24812)
at android.os.Binder.shellCommand(Binder.java:950)
at android.os.Binder.onTransact(Binder.java:834)
at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:4818)
at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:8887)
at android.os.Binder.execTransactInternal(Binder.java:1184)
at android.os.Binder.execTransact(Binder.java:1143)
255|ASUS_I006D:/ #

After a little searching on the Internet I found a very useful workaround on this page:

https://stackoverflow.com/questions...ling-new-limitations-of-data-local-tmp-folder

pm install also supports the installation of a package piped to stdin, e.g

cat [package_file] | pm install -S [package_size]

Example:

127|ASUS_I006D:/sdcard/Download # ls -l OmniStore.apk
-rw-rw---- 1 u0_a120 media_rw 4601419 2022-07-03 16:37 OmniStore.apk
ASUS_I006D:/sdcard/Download #
ASUS_I006D:/sdcard/Download # cat OmniStore.apk | pm install -S 4601419
Success
ASUS_I006D:/sdcard/Download #

Or, from the PC:

[xtrnaw7@t15g /data/backup/Android]$ adb shell id
uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_rw),1079(ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:shell:s0
[xtrnaw7@t15g /data/backup/Android]$

[xtrnaw7@t15g /data/backup/Android]$ cat EssentialApps/F-Droid.apk | adb shell pm install -S $( ls -l EssentialApps/F-Droid.apk | awk '{ print $5 }' )
Success
[xtrnaw7@t15g /data/backup/Android]$

So I wrote a little script to install one or more packages on an Android phone using this method.

The script can run on a PC with a connected phone with a working adb connection or in a shell on the phone

The usage of the script is:

#
# Usage on a phone:
#
# install_apk.sh [apk1|dir1 ... apk#|dir#]
#
# Usage on a PC:
#
# install_apk.sh [options_for_adb --] [apk1|dir1 ... apk#|dir#]
#
# apk# is the name of an apk file to install; dir# is a directory with apk files
# If a parameter is a directory the script will install all files with the extension .apk from that directory
#
# The options for adb are optional; the script will not check the options for adb
# the number of apk files or directories is only limited by the maxium parameter supported by the used shell.
#
# Set the variable PM_INSTALL_OPTIONS with additional options for the "pm install" command before starting the
# script if neccessary
#
# Prerequisites
# The packages to install must exist as file either on the PC or on the phone
# A shell on the phone or via adb command is required
# root access is NOT neccessary
#

Sample script output for running on tjhe phone:

ASUS_I006D:/storage/emulated/0/Download $ sh ./install_apk.sh myapps/ OmniStore.apk
Running on a phone
Directory found in the parameter: Installing all apk files found in the directory "myapps/"
The apks will be installed on the phone model ASUS_I006D with the serial number M6AIB760D0939LX
Installing these apks

myapps//Magisk-25.1_25100.apk
myapps//Magisk-v25.0.apk
myapps//MiXplorer_v6.58.4-API29_B22020920.apk
myapps//Notecase_Pro_1.2.2.apk
myapps//com.keramidas.TitaniumBackupAddon_v1.apk
myapps//com.keramidas.TitaniumBackup_v417.apk
OmniStore.apk

Installing the apk "myapps//Magisk-25.1_25100.apk" ...
Success
"myapps//Magisk-25.1_25100.apk" succcessfully installed

Installing the apk "myapps//Magisk-v25.0.apk" ...
Failure [INSTALL_FAILED_VERSION_DOWNGRADE: Package Verification Result]
ERROR: Error installing the apk "myapps//Magisk-v25.0.apk"

Installing the apk "myapps//MiXplorer_v6.58.4-API29_B22020920.apk" ...
Success
"myapps//MiXplorer_v6.58.4-API29_B22020920.apk" succcessfully installed

Installing the apk "myapps//Notecase_Pro_1.2.2.apk" ...
Success
"myapps//Notecase_Pro_1.2.2.apk" succcessfully installed

Installing the apk "myapps//com.keramidas.TitaniumBackupAddon_v1.apk" ...
Success
"myapps//com.keramidas.TitaniumBackupAddon_v1.apk" succcessfully installed

Installing the apk "myapps//com.keramidas.TitaniumBackup_v417.apk" ...
Success
"myapps//com.keramidas.TitaniumBackup_v417.apk" succcessfully installed

Installing the apk "OmniStore.apk" ...
Success
"OmniStore.apk" succcessfully installed

Installation summary
====================

6 package(s) successfully installed:

myapps//Magisk-25.1_25100.apk
myapps//MiXplorer_v6.58.4-API29_B22020920.apk
myapps//Notecase_Pro_1.2.2.apk
myapps//com.keramidas.TitaniumBackupAddon_v1.apk
myapps//com.keramidas.TitaniumBackup_v417.apk
OmniStore.apk

1 package(s) not installed:

myapps//Magisk-v25.0.apk

ASUS_I006D:/storage/emulated/0/Download $

Sample script output for running on a PC:

[xtrnaw7@t15g /data/backup/Android/myapps]$ /data/develop/android/install_apk.sh -d -- /data/backup/Android/myapps/ ./Notecase/Notecase_Pro_1.2.1.apk
Running on a PC
Using adb with the options " -d " to install the packages
Directory found in the parameter: Installing all apk files found in the directory "/data/backup/Android/myapps/"
The apks will be installed on the phone model ASUS_I006D with the serial number M6AIB760D0939LX
Installing these apks

/data/backup/Android/myapps//com.android.keepass_196.apk
/data/backup/Android/myapps//com.keramidas.TitaniumBackup_v417.apk
/data/backup/Android/myapps//com.matoski.adbm_v27.apk
/data/backup/Android/myapps//F-Droid.apk
/data/backup/Android/myapps//FoxMagiskModuleManager_0.4.0-rc1.apk
/data/backup/Android/myapps//Magisk-25.1_25100.apk
/data/backup/Android/myapps//MiXplorer_v6.58.4-API29_B22020920.apk
/data/backup/Android/myapps//Notecase_Pro_1.2.2.apk
./Notecase/Notecase_Pro_1.2.1.apk

Installing the apk "/data/backup/Android/myapps//com.android.keepass_196.apk" ...
Success
"/data/backup/Android/myapps//com.android.keepass_196.apk" succcessfully installed

Installing the apk "/data/backup/Android/myapps//com.keramidas.TitaniumBackup_v417.apk" ...
Success
"/data/backup/Android/myapps//com.keramidas.TitaniumBackup_v417.apk" succcessfully installed

Installing the apk "/data/backup/Android/myapps//com.matoski.adbm_v27.apk" ...
Success
"/data/backup/Android/myapps//com.matoski.adbm_v27.apk" succcessfully installed

Installing the apk "/data/backup/Android/myapps//F-Droid.apk" ...
Success
"/data/backup/Android/myapps//F-Droid.apk" succcessfully installed

Installing the apk "/data/backup/Android/myapps//FoxMagiskModuleManager_0.4.0-rc1.apk" ...
Success
"/data/backup/Android/myapps//FoxMagiskModuleManager_0.4.0-rc1.apk" succcessfully installed

Installing the apk "/data/backup/Android/myapps//Magisk-25.1_25100.apk" ...
Success
"/data/backup/Android/myapps//Magisk-25.1_25100.apk" succcessfully installed

Installing the apk "/data/backup/Android/myapps//MiXplorer_v6.58.4-API29_B22020920.apk" ...
Success
"/data/backup/Android/myapps//MiXplorer_v6.58.4-API29_B22020920.apk" succcessfully installed

Installing the apk "/data/backup/Android/myapps//Notecase_Pro_1.2.2.apk" ...
Success
"/data/backup/Android/myapps//Notecase_Pro_1.2.2.apk" succcessfully installed

ERROR: The file "./Notecase/Notecase_Pro_1.2.1.apk" does not exist or is not readable

Installation summary
====================

8 package(s) successfully installed:

/data/backup/Android/myapps//com.android.keepass_196.apk
/data/backup/Android/myapps//com.keramidas.TitaniumBackup_v417.apk
/data/backup/Android/myapps//com.matoski.adbm_v27.apk
/data/backup/Android/myapps//F-Droid.apk
/data/backup/Android/myapps//FoxMagiskModuleManager_0.4.0-rc1.apk
/data/backup/Android/myapps//Magisk-25.1_25100.apk
/data/backup/Android/myapps//MiXplorer_v6.58.4-API29_B22020920.apk
/data/backup/Android/myapps//Notecase_Pro_1.2.2.apk

1 package(s) not found:

./Notecase/Notecase_Pro_1.2.1.apk

[xtrnaw7@t15g /data/backup/Android/myapps]$

Notes:

Another method to install packages via script from an PC is

adb install [package]

This command copies the file to a temporary location on the phone and installs it then via "pm install".

e.g

[xtrnaw7@t15g /data/backup/Android/myapps]$ adb install F-Droid.apk
Performing Streamed Install
Success
[xtrnaw7@t15g /data/backup/Android/myapps]$

Another ugly and insecure method on the phone to install an apk file using pm install as root is

130|ASUS_I006D:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
ASUS_I006D:/ #
ASUS_I006D:/ # getenforce
Enforcing
ASUS_I006D:/ # setenforce 0
ASUS_I006D:/ #
ASUS_I006D:/ # getenforce
Permissive
ASUS_I006D:/ #
ASUS_I006D:/ # pm install /sdcard/Download/EssentialApps/com.matoski.adbm_v27.apk
avc: denied { read } for scontext=u:r:system_server:s0 tcontext=u:object_r:fuse:s0 tclass=file permissive=1
Success
ASUS_I006D:/ # setenforce 1
ASUS_I006D:/ #
ASUS_I006D:/ # getenforce
Enforcing
ASUS_I006D:/ #

pm install supports a lot of options -- to get the usage help for pm use

adb shell pm help

or on the phone

pm help

or see here: https://developer.android.com/studio/command-line/adb#pm (Google Account neccessary) or here: http://adbcommand.com/adbshell/pm

Update 06.07.2022

I attached the script to this entry but I can not see the attachment.

Therefor: The script is also available on my web site:

http://bnsmb.de/files/public/Android/install_apk.sh

Update 09.11.2022

The script is now attached to this post in a ZIP file

Update 18.12.2023

Android 14 does not allow the installation of apks based on outdated SDK versions anymore. Trying to install these kind of apks will end with an error message like this:

ASUS_I006D:/ $ ls -l /sdcard/Download/com.matoski.adbm_v27.apk
-rw-rw---- 1 u0_a125 media_rw 793506 2022-03-08 22:24 /sdcard/Download/com.matoski.adbm_v27.apk

ASUS_I006D:/ $ cat /sdcard/Download/com.matoski.adbm_v27.apk | pm install -S 793506
Failure [INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 23, but found 19]
1|ASUS_I006D:/ $

To get around this error use the additional parameter --bypass-low-target-sdk-block for the command pm , e.g.:

ASUS_I006D:/ $ ls -l /sdcard/Download/com.matoski.adbm_v27.apk
-rw-rw---- 1 u0_a125 media_rw 793506 2022-03-08 22:24 /sdcard/Download/com.matoski.adbm_v27.apk
1|ASUS_I006D:/ $
1|ASUS_I006D:/ $ cat /sdcard/Download/com.matoski.adbm_v27.apk | pm install --bypass-low-target-sdk-block -S 793506
Success
ASUS_I006D:/ $

To use this parameter with the script install_apk.sh define the environment variable PM_INSTALL_OPTIONS before executing the script:

[ OmniRom 13 Dev - xtrnaw7@t15g ~ ] $ export PM_INSTALL_OPTIONS="--bypass-low-target-sdk-block "

[ OmniRom 13 Dev - xtrnaw7@t15g ~ ] $ /data/develop/android/scripts/install_apk.sh /data/backup/Android/EssentialApps/com.matoski.adbm_v27.apk
Running on a PC
Using adb to install the packages
The apks will be installed on the phone model ASUS_I006D with the serial number M6AIB760D0939LX
Installing these apks

/data/backup/Android/EssentialApps/com.matoski.adbm_v27.apk

The additional parameter for the command "pm install" are: "--bypass-low-target-sdk-block "

Installing the apk "/data/backup/Android/EssentialApps/com.matoski.adbm_v27.apk" ...
Success
"/data/backup/Android/EssentialApps/com.matoski.adbm_v27.apk" succcessfully installed

Installation summary
====================

1 package(s) successfully installed:

/data/backup/Android/EssentialApps/com.matoski.adbm_v27.apk

[ OmniRom 13 Dev - xtrnaw7@t15g ~ ] $

Note:

Due to the outdated SDK used to create the app, it is important to test wether the app really works on Android 14!

Update 02.05.2024

if the installation of an apk file using this method fails with an error message like this:

Failure [INSTALL_PARSE_FAILED_NOT_APK: Failed to parse /data/app/vmdl643615185.tmp/base.apk: Failed to load asset path /data/app/vmdl643615185.tmp/base.apk]

you most probably used an invalid value for the size of the package to install.

There was an error in the script install_apk.sh.sh that used the wrong file size for installing apks using symbolic links - this error is fixed in the script version from the 02.05.2024.