Merge change 4111 into donut
* changes: Move package installation logic from ADT to ddmlib.
This commit is contained in:
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package com.android.ddmlib;
|
package com.android.ddmlib;
|
||||||
|
|
||||||
|
import com.android.ddmlib.SyncService.SyncResult;
|
||||||
import com.android.ddmlib.log.LogReceiver;
|
import com.android.ddmlib.log.LogReceiver;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -25,6 +27,8 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,11 +54,51 @@ final class Device implements IDevice {
|
|||||||
private final ArrayList<Client> mClients = new ArrayList<Client>();
|
private final ArrayList<Client> mClients = new ArrayList<Client>();
|
||||||
private DeviceMonitor mMonitor;
|
private DeviceMonitor mMonitor;
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "Device";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket for the connection monitoring client connection/disconnection.
|
* Socket for the connection monitoring client connection/disconnection.
|
||||||
*/
|
*/
|
||||||
private SocketChannel mSocketChannel;
|
private SocketChannel mSocketChannel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output receiver for "pm install package.apk" command line.
|
||||||
|
*/
|
||||||
|
private static final class InstallReceiver extends MultiLineReceiver {
|
||||||
|
|
||||||
|
private static final String SUCCESS_OUTPUT = "Success"; //$NON-NLS-1$
|
||||||
|
private static final Pattern FAILURE_PATTERN = Pattern.compile("Failure\\s+\\[(.*)\\]"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
private String mErrorMessage = null;
|
||||||
|
|
||||||
|
public InstallReceiver() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processNewLines(String[] lines) {
|
||||||
|
for (String line : lines) {
|
||||||
|
if (line.length() > 0) {
|
||||||
|
if (line.startsWith(SUCCESS_OUTPUT)) {
|
||||||
|
mErrorMessage = null;
|
||||||
|
} else {
|
||||||
|
Matcher m = FAILURE_PATTERN.matcher(line);
|
||||||
|
if (m.matches()) {
|
||||||
|
mErrorMessage = m.group(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return mErrorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see com.android.ddmlib.IDevice#getSerialNumber()
|
* @see com.android.ddmlib.IDevice#getSerialNumber()
|
||||||
@@ -373,4 +417,94 @@ final class Device implements IDevice {
|
|||||||
void addProperty(String label, String value) {
|
void addProperty(String label, String value) {
|
||||||
mProperties.put(label, value);
|
mProperties.put(label, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public String installPackage(String packageFilePath, boolean reinstall)
|
||||||
|
throws IOException {
|
||||||
|
String remoteFilePath = syncPackageToDevice(packageFilePath);
|
||||||
|
String result = installRemotePackage(remoteFilePath, reinstall);
|
||||||
|
removeRemotePackage(remoteFilePath);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public String syncPackageToDevice(String localFilePath)
|
||||||
|
throws IOException {
|
||||||
|
try {
|
||||||
|
String packageFileName = getFileName(localFilePath);
|
||||||
|
String remoteFilePath = String.format("/data/local/tmp/%1$s", packageFileName); //$NON-NLS-1$
|
||||||
|
|
||||||
|
Log.i(packageFileName, String.format("Uploading %1$s onto device '%2$s'",
|
||||||
|
packageFileName, getSerialNumber()));
|
||||||
|
|
||||||
|
SyncService sync = getSyncService();
|
||||||
|
if (sync != null) {
|
||||||
|
String message = String.format("Uploading file onto device '%1$s'",
|
||||||
|
getSerialNumber());
|
||||||
|
Log.i(LOG_TAG, message);
|
||||||
|
SyncResult result = sync.pushFile(localFilePath, remoteFilePath,
|
||||||
|
SyncService.getNullProgressMonitor());
|
||||||
|
|
||||||
|
if (result.getCode() != SyncService.RESULT_OK) {
|
||||||
|
throw new IOException(String.format("Unable to upload file: %1$s",
|
||||||
|
result.getMessage()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IOException("Unable to open sync connection!");
|
||||||
|
}
|
||||||
|
return remoteFilePath;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(LOG_TAG, String.format("Unable to open sync connection! reason: %1$s",
|
||||||
|
e.getMessage()));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to retrieve the file name given a local file path
|
||||||
|
* @param filePath full directory path to file
|
||||||
|
* @return {@link String} file name
|
||||||
|
*/
|
||||||
|
private String getFileName(String filePath) {
|
||||||
|
return new File(filePath).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public String installRemotePackage(String remoteFilePath, boolean reinstall)
|
||||||
|
throws IOException {
|
||||||
|
InstallReceiver receiver = new InstallReceiver();
|
||||||
|
String cmd = String.format(reinstall ? "pm install -r \"%1$s\"" : "pm install \"%1$s\"",
|
||||||
|
remoteFilePath);
|
||||||
|
executeShellCommand(cmd, receiver);
|
||||||
|
return receiver.getErrorMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void removeRemotePackage(String remoteFilePath) throws IOException {
|
||||||
|
// now we delete the app we sync'ed
|
||||||
|
try {
|
||||||
|
executeShellCommand("rm " + remoteFilePath, new NullOutputReceiver());
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(LOG_TAG, String.format("Failed to delete temporary package: %1$s",
|
||||||
|
e.getMessage()));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public String uninstallPackage(String packageName) throws IOException {
|
||||||
|
InstallReceiver receiver = new InstallReceiver();
|
||||||
|
executeShellCommand("pm uninstall " + packageName, receiver);
|
||||||
|
return receiver.getErrorMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ public interface IDevice {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link SyncService} object to push / pull files to and from the device.
|
* Returns a {@link SyncService} object to push / pull files to and from the device.
|
||||||
* @return <code>null</code> if the SyncService couldn't be created. This can happen if abd
|
* @return <code>null</code> if the SyncService couldn't be created. This can happen if adb
|
||||||
* refuse to open the connection because the {@link IDevice} is invalid (or got disconnected).
|
* refuse to open the connection because the {@link IDevice} is invalid (or got disconnected).
|
||||||
* @throws IOException if the connection with adb failed.
|
* @throws IOException if the connection with adb failed.
|
||||||
*/
|
*/
|
||||||
@@ -211,4 +211,48 @@ public interface IDevice {
|
|||||||
*/
|
*/
|
||||||
public String getClientName(int pid);
|
public String getClientName(int pid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs an Android application on device.
|
||||||
|
* This is a helper method that combines the syncPackageToDevice, installRemotePackage,
|
||||||
|
* and removePackage steps
|
||||||
|
* @param packageFilePath the absolute file system path to file on local host to install
|
||||||
|
* @param reinstall set to <code>true</code> if re-install of app should be performed
|
||||||
|
* @return a {@link String} with an error code, or <code>null</code> if success.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public String installPackage(String packageFilePath, boolean reinstall) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes a file to device
|
||||||
|
* @param localFilePath the absolute path to file on local host
|
||||||
|
* @return {@link String} destination path on device for file
|
||||||
|
* @throws IOException if fatal error occurred when pushing file
|
||||||
|
*/
|
||||||
|
public String syncPackageToDevice(String localFilePath)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs the application package that was pushed to a temporary location on the device.
|
||||||
|
* @param remoteFilePath absolute file path to package file on device
|
||||||
|
* @param reinstall set to <code>true</code> if re-install of app should be performed
|
||||||
|
* @throws InstallException if installation failed
|
||||||
|
*/
|
||||||
|
public String installRemotePackage(String remoteFilePath, boolean reinstall)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a file from device
|
||||||
|
* @param remoteFilePath path on device of file to remove
|
||||||
|
* @throws IOException if file removal failed
|
||||||
|
*/
|
||||||
|
public void removeRemotePackage(String remoteFilePath) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstall an package from the device.
|
||||||
|
* @param packageName the Android application package name to uninstall
|
||||||
|
* @return a {@link String} with an error code, or <code>null</code> if success.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public String uninstallPackage(String packageName) throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,6 +220,30 @@ public class RemoteAndroidTestRunnerTest extends TestCase {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String installPackage(String packageFilePath, boolean reinstall)
|
||||||
|
throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String uninstallPackage(String packageName) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String installRemotePackage(String remoteFilePath,
|
||||||
|
boolean reinstall) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRemotePackage(String remoteFilePath)
|
||||||
|
throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String syncPackageToDevice(String localFilePath)
|
||||||
|
throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,12 +21,9 @@ import com.android.ddmlib.Client;
|
|||||||
import com.android.ddmlib.ClientData;
|
import com.android.ddmlib.ClientData;
|
||||||
import com.android.ddmlib.IDevice;
|
import com.android.ddmlib.IDevice;
|
||||||
import com.android.ddmlib.Log;
|
import com.android.ddmlib.Log;
|
||||||
import com.android.ddmlib.MultiLineReceiver;
|
|
||||||
import com.android.ddmlib.SyncService;
|
|
||||||
import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener;
|
import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener;
|
||||||
import com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener;
|
import com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener;
|
||||||
import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
|
import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
|
||||||
import com.android.ddmlib.SyncService.SyncResult;
|
|
||||||
import com.android.ide.eclipse.adt.AdtPlugin;
|
import com.android.ide.eclipse.adt.AdtPlugin;
|
||||||
import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode;
|
import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode;
|
||||||
import com.android.ide.eclipse.adt.internal.launch.DelayedLaunchInfo.InstallRetryMode;
|
import com.android.ide.eclipse.adt.internal.launch.DelayedLaunchInfo.InstallRetryMode;
|
||||||
@@ -74,8 +71,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the launch of Android application either on a device or on the
|
* Controls the launch of Android application either on a device or on the
|
||||||
@@ -134,47 +129,6 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
|||||||
/** static instance for singleton */
|
/** static instance for singleton */
|
||||||
private static AndroidLaunchController sThis = new AndroidLaunchController();
|
private static AndroidLaunchController sThis = new AndroidLaunchController();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output receiver for "pm install package.apk" command line.
|
|
||||||
*/
|
|
||||||
private static final class InstallReceiver extends MultiLineReceiver {
|
|
||||||
|
|
||||||
private static final String SUCCESS_OUTPUT = "Success"; //$NON-NLS-1$
|
|
||||||
private static final Pattern FAILURE_PATTERN = Pattern.compile("Failure\\s+\\[(.*)\\]"); //$NON-NLS-1$
|
|
||||||
|
|
||||||
private String mSuccess = null;
|
|
||||||
|
|
||||||
public InstallReceiver() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processNewLines(String[] lines) {
|
|
||||||
for (String line : lines) {
|
|
||||||
if (line.length() > 0) {
|
|
||||||
if (line.startsWith(SUCCESS_OUTPUT)) {
|
|
||||||
mSuccess = null;
|
|
||||||
} else {
|
|
||||||
Matcher m = FAILURE_PATTERN.matcher(line);
|
|
||||||
if (m.matches()) {
|
|
||||||
mSuccess = m.group(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSuccess() {
|
|
||||||
return mSuccess;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** private constructor to enforce singleton */
|
/** private constructor to enforce singleton */
|
||||||
private AndroidLaunchController() {
|
private AndroidLaunchController() {
|
||||||
AndroidDebugBridge.addDebugBridgeChangeListener(this);
|
AndroidDebugBridge.addDebugBridgeChangeListener(this);
|
||||||
@@ -847,70 +801,29 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
|||||||
* @return true if the install succeeded.
|
* @return true if the install succeeded.
|
||||||
*/
|
*/
|
||||||
private boolean doSyncApp(DelayedLaunchInfo launchInfo, IDevice device) {
|
private boolean doSyncApp(DelayedLaunchInfo launchInfo, IDevice device) {
|
||||||
|
IPath path = launchInfo.getPackageFile().getLocation();
|
||||||
|
String fileName = path.lastSegment();
|
||||||
try {
|
try {
|
||||||
SyncService sync = device.getSyncService();
|
String message = String.format("Uploading %1$s onto device '%2$s'",
|
||||||
if (sync != null) {
|
fileName, device.getSerialNumber());
|
||||||
IPath path = launchInfo.getPackageFile().getLocation();
|
AdtPlugin.printToConsole(launchInfo.getProject(), message);
|
||||||
String message = String.format("Uploading %1$s onto device '%2$s'",
|
|
||||||
path.lastSegment(), device.getSerialNumber());
|
|
||||||
AdtPlugin.printToConsole(launchInfo.getProject(), message);
|
|
||||||
|
|
||||||
String osLocalPath = path.toOSString();
|
String remotePackagePath = device.syncPackageToDevice(path.toOSString());
|
||||||
String apkName = launchInfo.getPackageFile().getName();
|
boolean installResult = installPackage(launchInfo, remotePackagePath, device);
|
||||||
String remotePath = "/data/local/tmp/" + apkName; //$NON-NLS-1$
|
device.removeRemotePackage(remotePackagePath);
|
||||||
|
|
||||||
SyncResult result = sync.pushFile(osLocalPath, remotePath,
|
// if the installation succeeded, we register it.
|
||||||
SyncService.getNullProgressMonitor());
|
if (installResult) {
|
||||||
|
ApkInstallManager.getInstance().registerInstallation(
|
||||||
if (result.getCode() != SyncService.RESULT_OK) {
|
launchInfo.getProject(), device);
|
||||||
String msg = String.format("Failed to upload %1$s on '%2$s': %3$s",
|
|
||||||
apkName, device.getSerialNumber(), result.getMessage());
|
|
||||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that the package is uploaded, we can install it properly.
|
|
||||||
// This will check that there isn't another apk declaring the same package, or
|
|
||||||
// that another install used a different key.
|
|
||||||
boolean installResult = installPackage(launchInfo, remotePath, device);
|
|
||||||
|
|
||||||
// now we delete the app we sync'ed
|
|
||||||
try {
|
|
||||||
device.executeShellCommand("rm " + remotePath, new MultiLineReceiver() { //$NON-NLS-1$
|
|
||||||
@Override
|
|
||||||
public void processNewLines(String[] lines) {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (IOException e) {
|
|
||||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format(
|
|
||||||
"Failed to delete temporary package: %1$s", e.getMessage()));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the installation succeeded, we register it.
|
|
||||||
if (installResult) {
|
|
||||||
ApkInstallManager.getInstance().registerInstallation(
|
|
||||||
launchInfo.getProject(), device);
|
|
||||||
}
|
|
||||||
|
|
||||||
return installResult;
|
|
||||||
} else {
|
|
||||||
String msg = String.format(
|
|
||||||
"Failed to upload %1$s on device '%2$s': Unable to open sync connection!",
|
|
||||||
launchInfo.getPackageFile().getName(), device.getSerialNumber());
|
|
||||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
return installResult;
|
||||||
String msg = String.format(
|
}
|
||||||
"Failed to upload %1$s on device '%2$s': Unable to open sync connection!",
|
catch (IOException e) {
|
||||||
launchInfo.getPackageFile().getName(), device.getSerialNumber());
|
String msg = String.format("Failed to upload %1$s on device '%2$s'", fileName,
|
||||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg, e.getMessage());
|
device.getSerialNumber());
|
||||||
|
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,22 +901,19 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
|||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs the application package that was pushed to a temporary location on the device.
|
* Installs the application package on the device, and handles return result
|
||||||
* @param launchInfo The launch information
|
* @param launchInfo The launch information
|
||||||
* @param remotePath The remote path of the package.
|
* @param remotePath The remote path of the package.
|
||||||
* @param device The device on which the launch is done.
|
* @param device The device on which the launch is done.
|
||||||
*/
|
*/
|
||||||
private boolean installPackage(DelayedLaunchInfo launchInfo, final String remotePath,
|
private boolean installPackage(DelayedLaunchInfo launchInfo, final String remotePath,
|
||||||
final IDevice device) {
|
final IDevice device) {
|
||||||
|
|
||||||
String message = String.format("Installing %1$s...", launchInfo.getPackageFile().getName());
|
String message = String.format("Installing %1$s...", launchInfo.getPackageFile().getName());
|
||||||
AdtPlugin.printToConsole(launchInfo.getProject(), message);
|
AdtPlugin.printToConsole(launchInfo.getProject(), message);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String result = doInstall(launchInfo, remotePath, device, false /* reinstall */);
|
// try a reinstall first, because the most common case is the app is already installed
|
||||||
|
String result = doInstall(launchInfo, remotePath, device, true /* reinstall */);
|
||||||
|
|
||||||
/* For now we force to retry the install (after uninstalling) because there's no
|
/* For now we force to retry the install (after uninstalling) because there's no
|
||||||
* other way around it: adb install does not want to update a package w/o uninstalling
|
* other way around it: adb install does not want to update a package w/o uninstalling
|
||||||
@@ -1012,7 +922,10 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
|||||||
return checkInstallResult(result, device, launchInfo, remotePath,
|
return checkInstallResult(result, device, launchInfo, remotePath,
|
||||||
InstallRetryMode.ALWAYS);
|
InstallRetryMode.ALWAYS);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// do nothing, we'll return false
|
String msg = String.format(
|
||||||
|
"Failed to install %1$s on device '%2$s!",
|
||||||
|
launchInfo.getPackageFile().getName(), device.getSerialNumber());
|
||||||
|
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1033,7 +946,9 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
|||||||
if (result == null) {
|
if (result == null) {
|
||||||
AdtPlugin.printToConsole(launchInfo.getProject(), "Success!");
|
AdtPlugin.printToConsole(launchInfo.getProject(), "Success!");
|
||||||
return true;
|
return true;
|
||||||
} else if (result.equals("INSTALL_FAILED_ALREADY_EXISTS")) { //$NON-NLS-1$
|
}
|
||||||
|
else if (result.equals("INSTALL_FAILED_ALREADY_EXISTS")) { //$NON-NLS-1$
|
||||||
|
// this should never happen, since reinstall mode is used on the first attempt
|
||||||
if (retryMode == InstallRetryMode.PROMPT) {
|
if (retryMode == InstallRetryMode.PROMPT) {
|
||||||
boolean prompt = AdtPlugin.displayPrompt("Application Install",
|
boolean prompt = AdtPlugin.displayPrompt("Application Install",
|
||||||
"A previous installation needs to be uninstalled before the new package can be installed.\nDo you want to uninstall?");
|
"A previous installation needs to be uninstalled before the new package can be installed.\nDo you want to uninstall?");
|
||||||
@@ -1067,11 +982,10 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
|||||||
|
|
||||||
AdtPlugin.printToConsole(launchInfo.getProject(),
|
AdtPlugin.printToConsole(launchInfo.getProject(),
|
||||||
"Application already exists. Attempting to re-install instead...");
|
"Application already exists. Attempting to re-install instead...");
|
||||||
String res = doInstall(launchInfo, remotePath, device, true /* reinstall */);
|
String res = doInstall(launchInfo, remotePath, device, true /* reinstall */ );
|
||||||
return checkInstallResult(res, device, launchInfo, remotePath,
|
return checkInstallResult(res, device, launchInfo, remotePath,
|
||||||
InstallRetryMode.NEVER);
|
InstallRetryMode.NEVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(),
|
AdtPlugin.printErrorToConsole(launchInfo.getProject(),
|
||||||
"Installation error! The package already exists.");
|
"Installation error! The package already exists.");
|
||||||
} else if (result.equals("INSTALL_FAILED_INVALID_APK")) { //$NON-NLS-1$
|
} else if (result.equals("INSTALL_FAILED_INVALID_APK")) { //$NON-NLS-1$
|
||||||
@@ -1110,18 +1024,14 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private String doUninstall(IDevice device, DelayedLaunchInfo launchInfo) throws IOException {
|
private String doUninstall(IDevice device, DelayedLaunchInfo launchInfo) throws IOException {
|
||||||
InstallReceiver receiver = new InstallReceiver();
|
|
||||||
try {
|
try {
|
||||||
device.executeShellCommand("pm uninstall " + launchInfo.getPackageName(), //$NON-NLS-1$
|
return device.uninstallPackage(launchInfo.getPackageName());
|
||||||
receiver);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
String msg = String.format(
|
String msg = String.format(
|
||||||
"Failed to uninstall %1$s: %2$s", launchInfo.getPackageName(), e.getMessage());
|
"Failed to uninstall %1$s: %2$s", launchInfo.getPackageName(), e.getMessage());
|
||||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
|
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
return receiver.getSuccess();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1136,22 +1046,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
|||||||
*/
|
*/
|
||||||
private String doInstall(DelayedLaunchInfo launchInfo, final String remotePath,
|
private String doInstall(DelayedLaunchInfo launchInfo, final String remotePath,
|
||||||
final IDevice device, boolean reinstall) throws IOException {
|
final IDevice device, boolean reinstall) throws IOException {
|
||||||
InstallReceiver receiver = new InstallReceiver();
|
return device.installRemotePackage(remotePath, reinstall);
|
||||||
try {
|
|
||||||
String cmd = String.format(
|
|
||||||
reinstall ? "pm install -r \"%1$s\"" : "pm install \"%1$s\"", //$NON-NLS-1$ //$NON-NLS-2$
|
|
||||||
remotePath); //$NON-NLS-1$ //$NON-NLS-2$
|
|
||||||
device.executeShellCommand(cmd, receiver);
|
|
||||||
} catch (IOException e) {
|
|
||||||
String msg = String.format(
|
|
||||||
"Failed to install %1$s on device '%2$s': %3$s",
|
|
||||||
launchInfo.getPackageFile().getName(), device.getSerialNumber(),
|
|
||||||
e.getMessage());
|
|
||||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
return receiver.getSuccess();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user