PackageInstallerpublic 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_DETAILSActivity 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_IDAn integer session ID that an operation is working with. | public static final String | EXTRA_PACKAGE_NAMEPackage name that an operation is working with. | public static final String | EXTRA_STATUSCurrent 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_MESSAGEDetailed string representation of the status, including raw details that
are useful for debugging. | public static final String | EXTRA_OTHER_PACKAGE_NAMEAnother package name relevant to a status. This is typically the package
responsible for causing an operation failure. | public static final String | EXTRA_STORAGE_PATHStorage 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_ACTIONUser 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_SUCCESSThe operation succeeded. | public static final int | STATUS_FAILUREThe 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_BLOCKEDThe 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_ABORTEDThe 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_INVALIDThe 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_CONFLICTThe 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_STORAGEThe 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_INCOMPATIBLEThe 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 |
Methods Summary |
---|
public void | abandonSession(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()}.
try {
mInstaller.abandonSession(sessionId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
| public void | addSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback){@hide}
registerSessionCallback(callback);
| public void | addSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback, android.os.Handler handler){@hide}
registerSessionCallback(callback, handler);
| public int | createSession(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.
try {
return mInstaller.createSession(params, mInstallerPackageName, mUserId);
} catch (RuntimeException e) {
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
| public java.util.List | getAllSessions()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.List | getMySessions()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$SessionInfo | getSessionInfo(int sessionId)Return details for a specific session. No special permissions are
required to retrieve these details.
try {
return mInstaller.getSessionInfo(sessionId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
| public android.content.pm.PackageInstaller$Session | openSession(int sessionId)Open an existing session to actively perform work. To succeed, the caller
must be the owner of the install session.
try {
return new Session(mInstaller.openSession(sessionId));
} catch (RuntimeException e) {
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
| public void | registerSessionCallback(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 void | registerSessionCallback(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.
// 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 void | removeSessionCallback(android.content.pm.PackageInstaller$SessionCallback callback){@hide}
unregisterSessionCallback(callback);
| public void | setPermissionsResult(int sessionId, boolean accepted){@hide}
try {
mInstaller.setPermissionsResult(sessionId, accepted);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
| public void | uninstall(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 void | unregisterSessionCallback(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 void | updateSessionAppIcon(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.
try {
mInstaller.updateSessionAppIcon(sessionId, appIcon);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
| public void | updateSessionAppLabel(int sessionId, java.lang.CharSequence appLabel)Update the label representing the app being installed in a specific
session.
try {
final String val = (appLabel != null) ? appLabel.toString() : null;
mInstaller.updateSessionAppLabel(sessionId, val);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
|
|