Java tutorial
/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.tools.idea.sdk.wizard; import com.android.sdklib.repository.descriptors.IPkgDesc; import com.android.tools.idea.sdk.SdkState; import com.android.tools.idea.sdk.remote.UpdatablePkgInfo; import com.android.tools.idea.wizard.DialogWrapperHost; import com.android.tools.idea.wizard.DynamicWizard; import com.android.tools.idea.wizard.DynamicWizardPath; import com.android.tools.idea.wizard.ScopedStateStore; import com.google.common.collect.Sets; import com.intellij.icons.AllIcons; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.SystemInfo; import org.jetbrains.android.actions.RunAndroidSdkManagerAction; import org.jetbrains.android.sdk.AndroidSdkData; import org.jetbrains.android.sdk.AndroidSdkUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.List; import java.util.Set; import static com.android.tools.idea.wizard.WizardConstants.INSTALL_REQUESTS_KEY; import static com.android.tools.idea.wizard.WizardConstants.SKIPPED_INSTALL_REQUESTS_KEY; /** * Provides a wizard which can install a list of items. * <p> * Example usage: * <pre> * {@code public static class LaunchMe extends AnAction { public LaunchMe() { super("Launch SDK Quickfix Wizard"); } @Override public void actionPerformed(AnActionEvent e) { List<IPkgDesc> requestedPackages = Lists.newArrayListWithCapacity(3); FullRevision minBuildToolsRev = FullRevision.parseRevision(SdkConstants.MIN_BUILD_TOOLS_VERSION); requestedPackages.add(PkgDesc.Builder.newBuildTool(minBuildToolsRev).create()); requestedPackages.add(PkgDesc.Builder.newPlatform(new AndroidVersion(19, null), new MajorRevision(1), minBuildToolsRev).create()); SdkQuickfixWizard sdkQuickfixWizard = new SdkQuickfixWizard(null, null, requestedPackages); sdkQuickfixWizard.init(); sdkQuickfixWizard.show(); } } } * </pre> */ public class SdkQuickfixWizard extends DynamicWizard { private final List<IPkgDesc> myRequestedPackages; public SdkQuickfixWizard(@Nullable Project project, @Nullable Module module, List<IPkgDesc> requestedPackages) { this(project, module, requestedPackages, new DialogWrapperHost(project)); } public SdkQuickfixWizard(@Nullable Project project, @Nullable Module module, List<IPkgDesc> requestedPackages, DialogWrapperHost host) { super(project, module, "SDK Quickfix Installation", host); myRequestedPackages = requestedPackages; } @Nullable @Override public Icon getIcon() { return null; } @Override public void init() { ScopedStateStore state = getState(); addPath(new SdkQuickfixPath(getDisposable())); Set<IPkgDesc> problems = findProblemPackages(); int selectedOption = 1; // Install all, default when there are no problems. if (!problems.isEmpty()) { StringBuilder warningBuilder = new StringBuilder( "Due to your system configuration and the packages to be installed, \n" + "it is likely that the following packages cannot be successfully installed while "); warningBuilder.append(ApplicationNamesInfo.getInstance().getFullProductName()); warningBuilder.append( " is running. \n\nPlease exit and install the following packages using the standalone SDK manager:"); for (IPkgDesc problemPkg : problems) { warningBuilder.append("\n -"); warningBuilder.append(problemPkg.getListDescription()); } if (problems.size() == myRequestedPackages.size()) { selectedOption = Messages.showDialog(getProject(), warningBuilder.toString(), "Warning", new String[] { String.format("Exit %s and launch SDK Manager", ApplicationNamesInfo.getInstance().getProductName()), "Attempt to install packages" }, 0, AllIcons.General.Warning); } else { String[] options = new String[] { String.format("Exit %s and launch SDK Manager", ApplicationNamesInfo.getInstance().getProductName()), "Attempt to install all packages", "Install safe packages" }; selectedOption = Messages.showDialog(getProject(), warningBuilder.toString(), "Warning", options, 2, AllIcons.General.Warning); } } if (selectedOption == 0) { startSdkManagerAndExit(); } else { for (IPkgDesc desc : myRequestedPackages) { if (selectedOption == 2 && problems.contains(desc)) { state.listPush(SKIPPED_INSTALL_REQUESTS_KEY, desc); } else { state.listPush(INSTALL_REQUESTS_KEY, desc); } } } super.init(); } private void startSdkManagerAndExit() { // We know that the SDK exists since we already used it to look up the fact that a package is an upgrade. //noinspection ConstantConditions RunAndroidSdkManagerAction.runSpecificSdkManagerSynchronously(getProject(), AndroidSdkUtils.tryToChooseAndroidSdk().getLocation()); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { ApplicationManagerEx.getApplicationEx().exit(true, true); } }); } /** * Find packages that might not be able to be installed while studio is running. * Currently this means packages that are upgrades on windows systems, since windows locks files that are in use. * @return */ private Set<IPkgDesc> findProblemPackages() { Set<IPkgDesc> result = Sets.newHashSet(); if (!SystemInfo.isWindows) { return result; } SdkState state = SdkState.getInstance(AndroidSdkUtils.tryToChooseAndroidSdk()); state.loadSynchronously(SdkState.DEFAULT_EXPIRATION_PERIOD_MS, false, null, null, null, false); Set<String> available = Sets.newHashSet(); for (UpdatablePkgInfo update : state.getPackages().getUpdatedPkgs()) { if (update.hasRemote(false)) { available.add(update.getRemote(false).getPkgDesc().getInstallId()); } if (update.hasPreview()) { available.add(update.getRemote(true).getPkgDesc().getInstallId()); } } for (IPkgDesc request : myRequestedPackages) { if (available.contains(request.getInstallId())) { // This is an update result.add(request); } } return result; } @Override public void performFinishingActions() { List<IPkgDesc> skipped = myState.get(SKIPPED_INSTALL_REQUESTS_KEY); if (skipped != null && !skipped.isEmpty()) { StringBuilder warningBuilder = new StringBuilder( "The following packages were not installed.\n\n Would you like to exit "); warningBuilder.append(ApplicationNamesInfo.getInstance().getFullProductName()); warningBuilder.append(" and install the following packages using the standalone SDK manager?"); for (IPkgDesc problemPkg : skipped) { warningBuilder.append("\n"); warningBuilder.append(problemPkg.getListDescription()); } String restartOption = String.format("Exit %s and launch SDK Manager", ApplicationNamesInfo.getInstance().getProductName()); int result = Messages.showDialog(getProject(), warningBuilder.toString(), "Warning", new String[] { restartOption, "Skip installation" }, 0, AllIcons.General.Warning); if (result == 0) { startSdkManagerAndExit(); } } // We've already installed things, so clearly there's an SDK. AndroidSdkData data = AndroidSdkUtils.tryToChooseAndroidSdk(); SdkState.getInstance(data).loadAsync(SdkState.DEFAULT_EXPIRATION_PERIOD_MS, false, null, null, null, true); } @NotNull @Override protected String getProgressTitle() { return "Finishing install..."; } @Override protected String getWizardActionDescription() { return "Provides a method for handling quickfix SDK installation actions"; } private static class SdkQuickfixPath extends DynamicWizardPath { private Disposable myDisposable; private LicenseAgreementStep myLicenseAgreementStep; public SdkQuickfixPath(Disposable disposable) { myDisposable = disposable; } @Override protected void init() { myLicenseAgreementStep = new LicenseAgreementStep(myDisposable); addStep(myLicenseAgreementStep); addStep(new SmwOldApiDirectInstall(myDisposable)); } @NotNull @Override public String getPathName() { return "SDK Installation Quickfix"; } @Override public boolean performFinishingActions() { myLicenseAgreementStep.performFinishingActions(); return true; } } }