Install Android APK without prompt - android

We are writing an Android app that shows ads on large screens.
We have a backend where advertisers can select the ads, so they are updated almost instantly.
Because there will be a lot of Android boxes running (plugged into HDMI screens), we should be able to update our software remotely.
This is the case:
Main app is running continuously (unless turned off) and the users never see anything Android related.
We need an updater app that listens for updates and deletes the main apk, installs a new apk.
While updating we will show an activity with "Updating, please wait", until the new main apk is installed and showing.
What we need:
We need help on how to implement the update mechanism without prompting the user on ROOTED DEVICE.
What we have:
The updater app is hooked into the boot received event, where a service starts (this service will listen for updates, which will be implemented by a colleague soon).
The service can start an activity which will prompt the update info while updating.
In the updater activity
try {
Process proc = Runtime.getRuntime().exec(new String[]{"su", "pm install -r /mnt/sdcard/MYFOLDER/testAPK.apk"});
stringBuilder.append(String.valueOf(proc.waitFor()));
stringBuilder.append("\n");
} catch (Exception e) {
if (e instanceof IOException) {
Log.d(TAG, "IOException");
} else if (e instanceof InterruptedException) {
Log.d(TAG, "InterruptedException");
} else {
e.printStackTrace();
}
}
The StringBuilder prints 11, but does the same if I give random unexisting command..
In the Manifest
<!-- Permission to start UpdaterService on boot -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Install/delete permissions, only granted to system apps -->
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
The Install packages and delete packages are useless if I don't install my app as system app, am I correct?
Long story short, no installation of my test APK, and I have no idea how to solve this.
Any help would be appreciated!

You can simply use adb install command to install/update APK silently. Sample code is below
public static void InstallAPK(String filename){
File file = new File(filename);
if(file.exists()){
try {
String command;
command = "adb install -r " + filename;
Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command });
proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
OR
Please check
http://paulononaka.wordpress.com/2011/07/02/how-to-install-a-application-in-background-on-android/

public void InstallAPK(String filename){
Process process = Runtime.getRuntime().exec("su");
OutputStream out = process.getOutputStream();
String reinstall = "pm install -r " + filename + "\n";
String am = "am start -a android.intent.action.MAIN -n yourPackage/.MainActivity";
String cmd = reinstall + am + " &";
out.write(cmd.getBytes());
out.flush();
out.close();
process.waitFor();
}

Related

Install Android system app, silent update without Google play on rooted device.

I am trying to get my app to download an update from an ftp site, in the form of a new version of the apk. After download the apk should be installed silently, without any confirmation from a user. I have the download part under control. I can also do this with confirmation from the user. The problem is the silent update part.
From what I can tell the only way to do this is by installing the app as a system app. This is where I need some help.
I have tried alot of things. The most success I have had is the following:
Rooting the device.
Adding *android:sharedUserId="android.uid.system" to the manifest.
Adding the following permissions to the manifest:
android.permission.ACCESS_SUPERUSER and android.permission.INSTALL_PACKAGES
Signing the apk with Android Studio->Build->Generate Signed APK... using a signature generated like this:
./keytool-importkeypair -k google_certificate.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform
where I got the pk8 and pem files from the Android source mirror on GitHub.
Moving the signed apk to system/app on the device and clicking install on it.
The first thing I get is a huge list of permissions that the app is requesting which I never did. So I guess this is the permissions a system app has, so far so good :)
The immediately after I get the message:
App not installed.
Google could not tell why this error occures, so I am asking here.
Am I on the right path?
Why was the app not installed?
So after a couple of years I got to that problem again, and I managed to solve it. So the most important part is rooting the phone properly: This was done with the SuperSU app.
After downloading the .apk file, a method similar to the following is used to install the update:
private Boolean Install(String path)
{
File file = new File(path);
if(file.exists()){
try {
Process proc = Runtime.getRuntime().exec(new String[]{"su","-c","pm install -r -d " + path});
proc.waitFor();
BufferedReader input = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String line;
Boolean hasError = false;
while ((line = input.readLine()) != null) {
if(line.contains("Failure")){
hasError = true;
}
}
if(proc.exitValue() != 0 || hasError){
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
return false;
}
If you device is rooted you can execute this command:
pm install com.example.myapp
How to execute this command?
There are two ways:
Way #1:
Use RootTools library:
Command command = new Command(0, "pm install com.example.myapp") {
#Override
public void commandCompleted(int arg0, int arg1) {
Log.i(TAG, "App installation is completed");
}
#Override
public void commandOutput(int arg0, String line) {
}
#Override
public void commandTerminated(int arg0, String arg1) {
}
}
RootTools.getShell(true).add(command);
Way #2:
This way not requires libraries, but it's harder than first way.
//Start a new process with root privileges
Process process = Runtime.getRuntime().exec("su");
//Get OutputStream of su to write commands to su process
OutputStream out = process.getOutputStream();
//Your command
String cmd = "pm install com.example.myapp";
//Write the command to su process
out.write(cmd.getBytes());
//Flush the OutputStream
out.flush();
//Close the OutputStream
out.close();
//Wait until command
process.waitFor();
Log.i(TAG, "App installation is completed");

Get screenshot of current foreground app on Android having root priviliges

I'm developing an application that is installed on the system partition and I would like to know if it's possible to get a screenshot of the current foreground application from a service. Of course, the application being any third party app.
I'm not interested in security issues or anything related to that matter. I only want to get a snapshot of the current foreground third party app.
Note: I'm aware of the /system/bin/screencap solution but I'm looking for a more elegant alternative that does everything programmatically.
The method that I'm going to describe below will let you to programmatically take screen shots of whatever app it's in the foreground from a background process.
I am assuming that you have a rooted device.
I this case you can use the uiautomator framework to get the job done.
This framework has a been created to automate black box testing of apps on android, but it will suite this purpose as well.
We are going to use the method
takeScreenshot(File storePath, float scale, int quality)
This goes in the service class:
File f = new File(context.getApplicationInfo().dataDir, "test.jar");
//this command will start uiautomator
String cmd = String.format("uiautomator runtest %s -c com.mypacket.Test", f.getAbsoluteFile());
Process p = doCmds(cmd);
if(null != p)
{
p.waitFor();
}
else
{
Log.e(TAG, "starting the test FAILED");
}
private Process doCmds(String cmds)
{
try
{
Process su = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(su.getOutputStream());
os.writeBytes(cmds + "\n");
os.writeBytes("exit\n");
os.flush();
os.close();
return su;
}
catch(Exception e)
{
e.printStackTrace();
Log.e(TAG, "doCmds FAILED");
return null;
}
}
This is the class for uiautomator:
public class Test extends UiAutomatorTestCase
{
public void testDemo()
{
UiDevice dev = UiDevice.getInstance();
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
dev.takeScreenshot(f, 1.0, 100);
}
}
It's best if you create a background thread in which uiautomator will run, that way it will not run onto the ui thread. (the Service runs on the ui thread).
uiatuomator doesn't know about or have a android context.
Once uiautomator gets the control you will be able to call inside it android methods that do not take a context parameter or belong to the context class.
If you need to communicate between uiautomator and the service (or other android components) you can use LocalSocket.
This will allow communication in both ways.
Months have passed since I asked this question but just now had the time to add this feature. The way to do this is simply by calling screencap -p <file_name_absolute_path> and then grabbing the file. Next is the code I used:
private class WorkerTask extends AsyncTask<String, String, File> {
#Override
protected File doInBackground(String... params) {
File screenshotFile = new File(Environment.getExternalStorageDirectory().getPath(), SCREENSHOT_FILE_NAME);
try {
Process screencap = Runtime.getRuntime().exec("screencap -p " + screenshotFile.getAbsolutePath());
screencap.waitFor();
return screenshotFile;
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(File screenshot_file) {
// Do something with the file.
}
}
Remember to add the <uses-permission android:name="android.permission.READ_FRAME_BUFFER" /> permission to the manifest. Otherwise screenshot.png will be blank.
This is much simpler than what Goran stated and is what I finally used.
Note: It only worked for me when the app is installed on the system partition.

How to Shutdown Android 4.0 rooted Device programatically

Please help me to find out solution for this, I Know there are so many questions and duplicates about this same but here i describe whole things which i tried.
I have one android device where its installed 4.0 version of android.
I want to shutdown this device using my one demo application.
1) Demo application is signed by platform keys which are used in built in file system.
2) Device is already rooted as its development board and i have all permissions on this.
Application contains Following things
1) Application is system application
2) Application signed by platform keys which are used in built in file system.
For make automation easier, I did import the key/cert pair into my java keystore file, with the this keytool-importkeypair and use eclipse for signing.
Used command is mentioned below.
Commad : keytool-importkeypair -k ~/Desktop/myown.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform
I used following code for reboot but i never make success in this .I read So many questions and answers on stackoverflow but they all said you require
1) root access of device
2) signed apk with any one keys which are available on `build/target/product/security/`
3) Given Proper permission in AndroidManifest.xml file.
Am i right in alomg points?
Application code :
First Try
public static void shutdown2() {
Runtime runtime = Runtime.getRuntime();
Process proc = null;
OutputStreamWriter osw = null;
String command = "/system/bin/reboot -p";
try { // Run Script
proc = runtime.exec("/system/xbin/su");
osw = new OutputStreamWriter(proc.getOutputStream());
osw.write(command);
osw.flush();
osw.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
if (proc != null)
proc.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (proc.exitValue() != 0) {
}
}
Second Try :
private void shutdown3() {
try {
String[] cmd = { "/system/bin/sh","su","reboot -p"};
Process proc = Runtime.getRuntime().exec(cmd);
proc.waitFor();
} catch (Exception ex) {
Log.i("TAG", "Could not reboot 3 ", ex);
}
}
3rd Try :
private void shutdown() {
try {
Process proc = Runtime.getRuntime().exec(
new String[] { "/system/bin/su", "-c",
"/system/bin/reboot -p" });
proc.waitFor();
} catch (Exception ex) {
Log.i("TAG", "Could not reboot 1 ", ex);
}
}
In 3rd method I also tried with "/system/bin/su"
The below code worked for me
Process process = Runtime.getRuntime()
.exec(new String[]{ "su", "-c", "busybox poweroff -f"});
process.waitFor();
A much better solution is to run:
su -c am start -a android.intent.action.ACTION_REQUEST_SHUTDOWN
You can use a Process for this.

Android Install apk silently by busybox command-line

I want to install .apk silently in background by BusyBox command. I`ve seen some similar questions like THIS, but I still cant get working my code properly...
I have:
My .apk I need to install on /sdcard/download/app.apk
Root
BusyBox installed
Code (not working):
String sss = Environment.getExternalStorageDirectory() + "/download/" + "app.apk";
Process install;
install = Runtime.getRuntime().exec("/system/xbin/busybox pm install " + sss);
int success = install.waitFor();
If I use "install" instead of "pm install" it copies file well.
P.S. Code above is executing in AsyncTask. No errors, but also nothing happens...
Please help!
Also I tried this, but I`m getting exit value 139 and no result:
Process process;
process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("pm install /mnt/sdcard/app.apk\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
int i = process.waitFor();
maybe this code will help you
Process p = null;
try
{
p = Runtime.getRuntime().exec("su");
DataOutputStream outs=new DataOutputStream(p.getOutputStream());
String cmd="pm install /mnt/sdcard/app.apk";
outs.writeBytes(cmd+"\n");
}
catch (IOException e)
{
e.printStackTrace();
}
After a lot of investigations on many android devices I realized that this code is correct and works!
There was just some problem with one device (Samsung Galaxy Tab 2 7.0 - 4.0.3 ICS). Maybe that is some strange feature of ICS. After updating firmware to 4.1.2 (Jelly Bean) problem has been resolved.
You can simply use adb install command to install/update APK silently. Sample code is below
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();
}
}
}

Install apps silently, with granted INSTALL_PACKAGES permission

I am trying to silently install apk into the system.
My app is located in /system/app and successfully granted permission "android.permission.INSTALL_PACKAGES"
However I can't find anywhere how to use this permission. I tried to copy files to /data/app and had no success. Also I tried using this code
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.parse("file:///sdcard/app.apk"),
"application/vnd.android.package-archive");
startActivity(intent);
But this code opens standard installation dialog. How can I install app silently without root with granted android.permission.INSTALL_PACKAGES?
PS I am writing an app that will install many apks from folder into the system on the first start (replace Setup Wizard). I need it to make firmware lighter.
If you think that I am writing a virus: All programs are installed into /data/app. Permission Install_packages can only be granted to system-level programs located in /system/app or signed with the system key. So virus can't get there.
As said http://www.mail-archive.com/android-porting#googlegroups.com/msg06281.html apps CAN be silent installed if they have install_packages permission. Moreover you don't need Install_packages permission to install packages not silently. Plus http://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html
Your first bet is to look into Android's native PackageInstaller. I would recommend modifying that app the way you like, or just extract required functionality.
Specifically, if you look into PackageInstallerActivity and its method 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();
}
}
Then you'll notice that actual installer is located in InstallAppProgress class. Inspecting that class you'll find that initView is the core installer function, and the final thing it does is call to PackageManager's installPackage function:
public void initView() {
...
pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
}
Next step is to inspect PackageManager, which is abstract class. You'll find installPackage(...) function there. The bad news is that it's marked with #hide. This means it's not directly available (you won't be able to compile with call to this method).
/**
* #hide
* ....
*/
public abstract void installPackage(Uri packageURI,
IPackageInstallObserver observer,
int flags,String installerPackageName);
But you will be able to access this methods via reflection.
If you are interested in how PackageManager's installPackage function is implemented, take a look at PackageManagerService.
Summary
You'll need to get package manager object via Context's getPackageManager(). Then you will call installPackage function via reflection.
I have been implementing installation without user consent recently - it was a kiosk application for API level 21+ where I had full control over environment.
The basic requirements are
API level 21+
root access to install the updater as a system privileged app.
The following method reads and installs APK from InputStream:
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;
}
The following code calls the installation
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();
}
for the whole thing to work you desperately need INSTALL_PACKAGES permission, or the code above will fail silently
<uses-permission
android:name="android.permission.INSTALL_PACKAGES" />
to get this permission you must install your APK as System application which REQUIRES root (however AFTER you have installed your updater application it seem to work WITHOUT root)
To install as system application I created a signed APK and pushed it with
adb push updater.apk /sdcard/updater.apk
and then moved it to system/priv-app - which requires remounting FS (this is why the root is required)
adb shell
su
mount -o rw,remount /system
mv /sdcard/updater.apk /system/priv-app
chmod 644 /system/priv-app/updater.apk
for some reason it didn't work with simple debug version, but logcat shows useful info if your application in priv-app is not picked up for some reason.
I have checked how ADB installs apps.
- It copies the APK to /data/local/tmp
- it runs 'shell:pm install /data/local/tmp/app.apk'
I have tried to replicate this behaviour by doing: (on pc, using usb-cable)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
This works. The app is installed.
I made an application (named AppInstall) which should install the other app.
(installed normally, non-rooted device)
It does:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
But this gives the error:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
It seems like the error is thrown by pm, not by AppInstall.
Because the SecurityException is not catched by AppInstall and the app does not crash.
I've tried the same thing on a rooted device (same app and AppInstall) and it worked like a charm.
(Also normally installed, not in /system or anything)
AppInstall didn't even ask root-permission.
But thats because the shell is always # instead of $ on that device.
Btw, you need root to install an app in /system, correct?
I tried adb remount on the non-rooted device and got:
remount failed: Operation not permitted.
That's why I could not try the /system thing on the non-rooted device.
Conclusion: you should use a rooted device
Hope this helps :)
You should define
<uses-permission
android:name="android.permission.INSTALL_PACKAGES" />
in your manifest, then if whether you are in system partition (/system/app) or you have your application signed by the manufacturer, you are going to have INSTALL_PACKAGES permission.
My suggestion is to create a little android project with 1.5 compatibility level used to call installPackages via reflection and to export a jar with methods to install packages and to call the real methods.
Then, by importing the jar in your project you will be ready to install packages.
I tried on rooted Android 4.2.2 and this method works for me:
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();
}
}
}
I had no idea of how to do this, because nobody answered that time, and I found no documentation about this permission. So I found my own solution. It is worser that yours, but this is a solution anyway.
I installed busybox, that set 777 permission to /data/app (I dont care about security). Then just executed "busybox install" from app. This works, but has a big security leak. If you set permissions 777, no root required.
You can use the hidden API android.content.pm.IPackageInstallObserver by reflection:
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();
}
}
}
Import android.content.pm.IPackageInstallObserver into your project. Your app must be system. You must activate the permission android.permission.INSTALL_PACKAGES in your manifest file.
You can simply use adb install command to install/update APK silently. Sample code is below
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();
}
}
}
I checked all the answers, the conclusion seems to be you must have root access to the device first to make it work.
But then I found these articles very useful. Since I'm making "company-owned" devices.
How to Update Android App Silently Without User Interaction
Android Device Owner - Minimal App
Here is google's the documentation about "managed-device"
Fully managed device
Prerequisite:
Your APK needs to be signed by system as correctly pointed out earlier. One way to achieve that is building the AOSP image yourself and adding the source code into the build.
Code:
Once installed as a system app, you can use the package manager methods to install and uninstall an APK as following:
Install:
public boolean install(final String apkPath, final Context context) {
Log.d(TAG, "Installing apk at " + apkPath);
try {
final Uri apkUri = Uri.fromFile(new File(apkPath));
final String installerPackageName = "MyInstaller";
context.getPackageManager().installPackage(apkUri, installObserver, PackageManager.INSTALL_REPLACE_EXISTING, installerPackageName);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
Uninstall:
public boolean uninstall(final String packageName, final Context context) {
Log.d(TAG, "Uninstalling package " + packageName);
try {
context.getPackageManager().deletePackage(packageName, deleteObserver, PackageManager.DELETE_ALL_USERS);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
To have a callback once your APK is installed/uninstalled you can use this:
/**
* Callback after a package was installed be it success or failure.
*/
private class InstallObserver implements IPackageInstallObserver {
#Override
public void packageInstalled(String packageName, int returnCode) throws RemoteException {
if (packageName != null) {
Log.d(TAG, "Successfully installed package " + packageName);
callback.onAppInstalled(true, packageName);
} else {
Log.e(TAG, "Failed to install package.");
callback.onAppInstalled(false, null);
}
}
#Override
public IBinder asBinder() {
return null;
}
}
/**
* Callback after a package was deleted be it success or failure.
*/
private class DeleteObserver implements IPackageDeleteObserver {
#Override
public void packageDeleted(String packageName, int returnCode) throws RemoteException {
if (packageName != null) {
Log.d(TAG, "Successfully uninstalled package " + packageName);
callback.onAppUninstalled(true, packageName);
} else {
Log.e(TAG, "Failed to uninstall package.");
callback.onAppUninstalled(false, null);
}
}
#Override
public IBinder asBinder() {
return null;
}
}
/**
* Callback to give the flow back to the calling class.
*/
public interface InstallerCallback {
void onAppInstalled(final boolean success, final String packageName);
void onAppUninstalled(final boolean success, final String packageName);
}
===> Tested on Android 8.1 and worked well.
I made a test app for silent installs, using PackageManager.installPackage method.
I get installPackage method through reflection, and made android.content.pm.IPackageInstallObserver interface in my src folder (because it's hidden in android.content.pm package).
When i run installPackage, i got SecurityException with string indication, that my app has no android.permission.INSTALL_PACKAGES, but it defined in AndroidManifest.xml.
So, i think, it's not possible to use this method.
PS. I tested in on Android SDK 2.3 and 4.0. Maybe it will work with earlier versions.
Try this LD_LIBRARY_PATH=/vendor/lib:/system/lib before pm install. It works well.
An 3rd party application cannot install an Android App sliently.
However, a 3rd party application can ask the Android OS to install a application.
So you should define this:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///sdcard/app.apk", "application/vnd.android.package-archive");
startActivity(intent);
You can also try to install it as a system app to grant the permission and ignore this define. (Root Required)
You can run the following command on your 3rd party app to install an app on the rooted device.
The code is:
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();
}
}
}
I hope that this answer is helpful for you.
Its possible to do silent install on Android 6 and above. Using the function supplied in the answer by Boris Treukhov, ignore everything else in the post, root is not required either.
Install your app as device admin, you can have full kiosk mode with silent install of updates in the background.
you can use this in terminal or shell
adb shell install -g MyApp.apk
see more in develope google
As #inazaruk mentioned in the answer, installPackage method in hidden, and you need to call it by reflection. But, IPackageInstallObserver callback is also hidden which is passed to installPackage as a parameter, so you need to use a Dynamic Proxy to be able to implement this interface. Below you can find a code snippet ysing both reflection and proxy:
private void silentAppInstall(Uri apkUri){
PackageManager pm = getContext().getPackageManager();
try {
Class<?> cPackageInstallObserver = Class.forName("android.content.pm.IPackageInstallObserver");
Object installObserver = Proxy.newProxyInstance(cPackageInstallObserver.getClassLoader(),
new Class[]{cPackageInstallObserver}, new InstallObserverHandler());
Class<?>[] types = new Class[] {Uri.class, cPackageInstallObserver, int.class, String.class};
Method method = pm.getClass().getMethod("installPackage", types);
method.invoke(pm, apkUri, installObserver, 2, null);
} catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
static class InstallObserverHandler implements InvocationHandler {
#Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
if (method.getName().equals("packageInstalled")){
// Place you code here
}
return null;
}
}
!/bin/bash
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
This works for me.
I run this on ubuntu 12.04, on shell terminal.

Categories

Resources