Skip to content

Instantly share code, notes, and snippets.

@dagezi
Created March 12, 2014 05:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dagezi/9501179 to your computer and use it in GitHub Desktop.
Save dagezi/9501179 to your computer and use it in GitHub Desktop.
package com.quipper.appdater;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.Context;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.RemoteException;
// Fake Package Manager
// @see http://paulononaka.wordpress.com/2011/07/02/how-to-install-a-application-in-background-on-android/
public class FakePackageManager {
// Following constants are copied from android/content/pm/PackageManager.java
/**
* Flag parameter for {@link #installPackage(android.net.Uri, int)} to
* indicate that this package should be installed as forward locked, i.e. only the app itself
* should have access to its code and non-resource assets.
*/
public static final int INSTALL_FORWARD_LOCK = 0x00000001;
/**
* Flag parameter for {@link #installPackage} to indicate that you want to replace an already
* installed package, if one exists.
*/
public static final int INSTALL_REPLACE_EXISTING = 0x00000002;
/**
* Flag parameter for {@link #installPackage} to indicate that you want to
* allow test packages (those that have set android:testOnly in their
* manifest) to be installed.
*/
public static final int INSTALL_ALLOW_TEST = 0x00000004;
/**
* Flag parameter for {@link #installPackage} to indicate that this
* package has to be installed on the sdcard.
*/
public static final int INSTALL_EXTERNAL = 0x00000008;
/**
* Flag parameter for {@link #installPackage} to indicate that this package
* has to be installed on the sdcard.
*/
public static final int INSTALL_INTERNAL = 0x00000010;
/**
* Flag parameter for {@link #installPackage} to indicate that this install
* was initiated via ADB.
*
*/
public static final int INSTALL_FROM_ADB = 0x00000020;
/**
* Flag parameter for {@link #installPackage} to indicate that this install
* should immediately be visible to all users.
*
*/
public static final int INSTALL_ALL_USERS = 0x00000040;
/**
* Flag parameter for {@link #installPackage} to indicate that it is okay
* to install an update to an app where the newly installed app has a lower
* version code than the currently installed app.
*
*/
public static final int INSTALL_ALLOW_DOWNGRADE = 0x00000080;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} on success.
*/
public static final int INSTALL_SUCCEEDED = 1;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if the package is
* already installed.
*/
public static final int INSTALL_FAILED_ALREADY_EXISTS = -1;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if the package archive
* file is invalid.
*/
public static final int INSTALL_FAILED_INVALID_APK = -2;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if the URI passed in
* is invalid.
*/
public static final int INSTALL_FAILED_INVALID_URI = -3;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if the package manager
* service found that the device didn't have enough storage space to install the app.
*/
public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if a
* package is already installed with the same name.
*/
public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the requested shared user does not exist.
*/
public static final int INSTALL_FAILED_NO_SHARED_USER = -6;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* a previously installed package of the same name has a different signature
* than the new package (and the old package's data was not removed).
*/
public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package is requested a shared user which is already installed on the
* device and does not have matching signature.
*/
public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package uses a shared library that is not available.
*/
public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package uses a shared library that is not available.
*/
public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package failed while optimizing and validating its dex files,
* either because there was not enough storage or the validation failed.
*/
public static final int INSTALL_FAILED_DEXOPT = -11;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package failed because the current SDK version is older than
* that required by the package.
*/
public static final int INSTALL_FAILED_OLDER_SDK = -12;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package failed because it contains a content provider with the
* same authority as a provider already installed in the system.
*/
public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package failed because the current SDK version is newer than
* that required by the package.
*/
public static final int INSTALL_FAILED_NEWER_SDK = -14;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package failed because it has specified that it is a test-only
* package and the caller has not supplied the {@link #INSTALL_ALLOW_TEST}
* flag.
*/
public static final int INSTALL_FAILED_TEST_ONLY = -15;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the package being installed contains native code, but none that is
* compatible with the the device's CPU_ABI.
*/
public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package uses a feature that is not available.
*/
public static final int INSTALL_FAILED_MISSING_FEATURE = -17;
// ------ Errors related to sdcard
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* a secure container mount point couldn't be accessed on external media.
*/
public static final int INSTALL_FAILED_CONTAINER_ERROR = -18;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package couldn't be installed in the specified install
* location.
*/
public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package couldn't be installed in the specified install
* location because the media is not available.
*/
public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package couldn't be installed because the verification timed out.
*/
public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package couldn't be installed because the verification did not succeed.
*/
public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the package changed from what the calling program expected.
*/
public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package is assigned a different UID than it previously held.
*/
public static final int INSTALL_FAILED_UID_CHANGED = -24;
/**
* Installation return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)} if
* the new package has an older version code than the currently installed package.
*/
public static final int INSTALL_FAILED_VERSION_DOWNGRADE = -25;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser was given a path that is not a file, or does not end with the expected
* '.apk' extension.
*/
public static final int INSTALL_PARSE_FAILED_NOT_APK = -100;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser was unable to retrieve the AndroidManifest.xml file.
*/
public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser encountered an unexpected exception.
*/
public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser did not find any certificates in the .apk.
*/
public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser found inconsistent certificates on the files in the .apk.
*/
public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser encountered a CertificateEncodingException in one of the
* files in the .apk.
*/
public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser encountered a bad or missing package name in the manifest.
*/
public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser encountered a bad shared user id name in the manifest.
*/
public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser encountered some structural problem in the manifest.
*/
public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108;
/**
* Installation parse return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the parser did not find any actionable tags (instrumentation or application)
* in the manifest.
*/
public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109;
/**
* Installation failed return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the system failed to install the package because of system issues.
*/
public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;
/**
* Installation failed return code: this is passed to the {@link OnPackageInstalledListener} by
* {@link #installPackage(android.net.Uri, int)}
* if the system failed to install the package because the user is restricted from installing
* apps.
*/
public static final int INSTALL_FAILED_USER_RESTRICTED = -111;
// The constants above are copied from android/content/pm/PackageManager.java
public interface OnPackageInstalledListener {
void onPackageInstalled(String packageName, int returnCode);
}
private PackageInstallObserver observer;
private PackageManager pm;
private Method method;
private OnPackageInstalledListener listener;
class PackageInstallObserver extends IPackageInstallObserver.Stub {
public void packageInstalled(String packageName, int returnCode) throws RemoteException {
if (listener != null) {
listener.onPackageInstalled(packageName, returnCode);
}
}
}
public FakePackageManager(Context context) throws SecurityException, NoSuchMethodException {
observer = new PackageInstallObserver();
pm = context.getPackageManager();
Class<?>[] types =
new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class};
method = pm.getClass().getMethod("installPackage", types);
}
public void setOnPackageInstalledListener(OnPackageInstalledListener listener) {
this.listener = listener;
}
public void installPackage(Uri apkFile, int flags) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
method.invoke(pm, new Object[] {apkFile, observer, flags, null});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment