FileDocCategorySizeDatePackage
PackageInstaller.javaAPI DocAndroid 5.1 API46150Thu Mar 12 22:22:10 GMT 2015android.content.pm

PackageInstaller

public class PackageInstaller extends Object
Offers the ability to install, upgrade, and remove applications on the device. This includes support for apps packaged either as a single "monolithic" APK, or apps packaged as multiple "split" APKs.

An app is delivered for installation through a {@link PackageInstaller.Session}, which any app can create. Once the session is created, the installer can stream one or more APKs into place until it decides to either commit or destroy the session. Committing may require user intervention to complete the installation.

Sessions can install brand new apps, upgrade existing apps, or add new splits into an existing app.

Apps packaged as multiple split APKs always consist of a single "base" APK (with a {@code null} split name) and zero or more "split" APKs (with unique split names). Any subset of these APKs can be installed together, as long as the following constraints are met:

  • All APKs must have the exact same package name, version code, and signing certificates.
  • All APKs must have unique split names.
  • All installations must contain a single base APK.

Fields Summary
private static final String
TAG
public static final String
ACTION_SESSION_DETAILS
Activity Action: Show details about a particular install session. This may surface actions such as pause, resume, or cancel.

This should always be scoped to the installer package that owns the session. Clients should use {@link SessionInfo#createDetailsIntent()} to build this intent correctly.

In some cases, a matching Activity may not exist, so ensure you safeguard against this.

The session to show details for is defined in {@link #EXTRA_SESSION_ID}.

public static final String
ACTION_CONFIRM_PERMISSIONS
{@hide}
public static final String
EXTRA_SESSION_ID
An integer session ID that an operation is working with.
public static final String
EXTRA_PACKAGE_NAME
Package name that an operation is working with.
public static final String
EXTRA_STATUS
Current status of an operation. Will be one of {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS}, {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED}, {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT}, {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or {@link #STATUS_FAILURE_STORAGE}.

More information about a status may be available through additional extras; see the individual status documentation for details.

public static final String
EXTRA_STATUS_MESSAGE
Detailed string representation of the status, including raw details that are useful for debugging.
public static final String
EXTRA_OTHER_PACKAGE_NAME
Another package name relevant to a status. This is typically the package responsible for causing an operation failure.
public static final String
EXTRA_STORAGE_PATH
Storage path relevant to a status.
public static final String
EXTRA_PACKAGE_NAMES
{@hide}
public static final String
EXTRA_LEGACY_STATUS
{@hide}
public static final String
EXTRA_LEGACY_BUNDLE
{@hide}
public static final String
EXTRA_CALLBACK
{@hide}
public static final int
STATUS_PENDING_USER_ACTION
User action is currently required to proceed. You can launch the intent activity described by {@link Intent#EXTRA_INTENT} to involve the user and continue.

You may choose to immediately launch the intent if the user is actively using your app. Otherwise, you should use a notification to guide the user back into your app before launching.

public static final int
STATUS_SUCCESS
The operation succeeded.
public static final int
STATUS_FAILURE
The operation failed in a generic way. The system will always try to provide a more specific failure reason, but in some rare cases this may be delivered.
public static final int
STATUS_FAILURE_BLOCKED
The operation failed because it was blocked. For example, a device policy may be blocking the operation, a package verifier may have blocked the operation, or the app may be required for core system operation.

The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the specific package blocking the install.

public static final int
STATUS_FAILURE_ABORTED
The operation failed because it was actively aborted. For example, the user actively declined requested permissions, or the session was abandoned.
public static final int
STATUS_FAILURE_INVALID
The operation failed because one or more of the APKs was invalid. For example, they might be malformed, corrupt, incorrectly signed, mismatched, etc.
public static final int
STATUS_FAILURE_CONFLICT
The operation failed because it conflicts (or is inconsistent with) with another package already installed on the device. For example, an existing permission, incompatible certificates, etc. The user may be able to uninstall another app to fix the issue.

The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the specific package identified as the cause of the conflict.

public static final int
STATUS_FAILURE_STORAGE
The operation failed because of storage issues. For example, the device may be running low on space, or external media may be unavailable. The user may be able to help free space or insert different external media.

The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to the storage device that caused the failure.

public static final int
STATUS_FAILURE_INCOMPATIBLE
The operation failed because it is fundamentally incompatible with this device. For example, the app may require a hardware feature that doesn't exist, it may be missing native code for the ABIs supported by the device, or it requires a newer SDK version, etc.
private final android.content.Context
mContext
private final PackageManager
mPm
private final IPackageInstaller
mInstaller
private final int
mUserId
private final String
mInstallerPackageName
private final ArrayList
mDelegates
Constructors Summary
public PackageInstaller(android.content.Context context, PackageManager pm, IPackageInstaller installer, String installerPackageName, int userId)
{@hide}


      
          
                
        mContext = context;
        mPm = pm;
        mInstaller = installer;
        mInstallerPackageName = installerPackageName;
        mUserId = userId;
    
Methods Summary
public voidabandonSession(int sessionId)
Completely abandon the given session, destroying all staged data and rendering it invalid. Abandoned sessions will be reported to {@link SessionCallback} listeners as failures. This is equivalent to opening the session and calling {@link Session#abandon()}.

throws
SecurityException when the caller does not own the session, or the session is invalid.

        try {
            mInstaller.abandonSession(sessionId);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public voidaddSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback)
{@hide}

        registerSessionCallback(callback);
    
public voidaddSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback, android.os.Handler handler)
{@hide}

        registerSessionCallback(callback, handler);
    
public intcreateSession(android.content.pm.PackageInstaller$SessionParams params)
Create a new session using the given parameters, returning a unique ID that represents the session. Once created, the session can be opened multiple times across multiple device boots.

The system may automatically destroy sessions that have not been finalized (either committed or abandoned) within a reasonable period of time, typically on the order of a day.

throws
IOException if parameters were unsatisfiable, such as lack of disk space or unavailable media.
throws
SecurityException when installation services are unavailable, such as when called from a restricted user.
throws
IllegalArgumentException when {@link SessionParams} is invalid.
return
positive, non-zero unique ID that represents the created session. This ID remains consistent across device reboots until the session is finalized. IDs are not reused during a given boot.

        try {
            return mInstaller.createSession(params, mInstallerPackageName, mUserId);
        } catch (RuntimeException e) {
            ExceptionUtils.maybeUnwrapIOException(e);
            throw e;
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public java.util.ListgetAllSessions()
Return list of all known install sessions, regardless of the installer.

        final ApplicationInfo info = mContext.getApplicationInfo();
        if ("com.google.android.googlequicksearchbox".equals(info.packageName)
                && info.versionCode <= 300400110) {
            Log.d(TAG, "Ignoring callback request from old prebuilt");
            return Collections.EMPTY_LIST;
        }

        try {
            return mInstaller.getAllSessions(mUserId).getList();
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public java.util.ListgetMySessions()
Return list of all known install sessions owned by the calling app.

        try {
            return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public android.content.pm.PackageInstaller$SessionInfogetSessionInfo(int sessionId)
Return details for a specific session. No special permissions are required to retrieve these details.

return
details for the requested session, or {@code null} if the session does not exist.

        try {
            return mInstaller.getSessionInfo(sessionId);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public android.content.pm.PackageInstaller$SessionopenSession(int sessionId)
Open an existing session to actively perform work. To succeed, the caller must be the owner of the install session.

throws
IOException if parameters were unsatisfiable, such as lack of disk space or unavailable media.
throws
SecurityException when the caller does not own the session, or the session is invalid.

        try {
            return new Session(mInstaller.openSession(sessionId));
        } catch (RuntimeException e) {
            ExceptionUtils.maybeUnwrapIOException(e);
            throw e;
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public voidregisterSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback)
Register to watch for session lifecycle events. No special permissions are required to watch for these events.

        registerSessionCallback(callback, new Handler());
    
public voidregisterSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback, android.os.Handler handler)
Register to watch for session lifecycle events. No special permissions are required to watch for these events.

param
handler to dispatch callback events through, otherwise uses calling thread.

        // TODO: remove this temporary guard once we have new prebuilts
        final ApplicationInfo info = mContext.getApplicationInfo();
        if ("com.google.android.googlequicksearchbox".equals(info.packageName)
                && info.versionCode <= 300400110) {
            Log.d(TAG, "Ignoring callback request from old prebuilt");
            return;
        }

        synchronized (mDelegates) {
            final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
                    handler.getLooper());
            try {
                mInstaller.registerCallback(delegate, mUserId);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
            mDelegates.add(delegate);
        }
    
public voidremoveSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback)
{@hide}

        unregisterSessionCallback(callback);
    
public voidsetPermissionsResult(int sessionId, boolean accepted)
{@hide}

        try {
            mInstaller.setPermissionsResult(sessionId, accepted);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public voiduninstall(java.lang.String packageName, android.content.IntentSender statusReceiver)
Uninstall the given package, removing it completely from the device. This method is only available to the current "installer of record" for the package.

        try {
            mInstaller.uninstall(packageName, 0, statusReceiver, mUserId);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public voidunregisterSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback)
Unregister a previously registered callback.

        synchronized (mDelegates) {
            for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
                final SessionCallbackDelegate delegate = i.next();
                if (delegate.mCallback == callback) {
                    try {
                        mInstaller.unregisterCallback(delegate);
                    } catch (RemoteException e) {
                        throw e.rethrowAsRuntimeException();
                    }
                    i.remove();
                }
            }
        }
    
public voidupdateSessionAppIcon(int sessionId, android.graphics.Bitmap appIcon)
Update the icon representing the app being installed in a specific session. This should be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.

throws
SecurityException when the caller does not own the session, or the session is invalid.

        try {
            mInstaller.updateSessionAppIcon(sessionId, appIcon);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    
public voidupdateSessionAppLabel(int sessionId, java.lang.CharSequence appLabel)
Update the label representing the app being installed in a specific session.

throws
SecurityException when the caller does not own the session, or the session is invalid.

        try {
            final String val = (appLabel != null) ? appLabel.toString() : null;
            mInstaller.updateSessionAppLabel(sessionId, val);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }