/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php * * 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.ide.eclipse.adt.internal.welcome; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog; import com.android.sdkstats.DdmsPreferenceStore; import com.android.sdkuilib.internal.repository.ui.AdtUpdateDialog; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.wizard.Wizard; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import java.io.File; import java.util.HashSet; import java.util.Set; /** * Wizard shown on first start for new users: configure SDK location, accept or * reject usage data collection, etc */ public class WelcomeWizard extends Wizard { private final DdmsPreferenceStore mStore; private WelcomeWizardPage mWelcomePage; private UsagePermissionPage mUsagePage; private final boolean mShowWelcomePage; private final boolean mShowUsagePage; /** * Creates a new {@link WelcomeWizard} * * @param store preferences for usage statistics collection etc * @param showInstallSdkPage show page to install SDK's * @param showUsageOptinPage show page to get user consent for usage data collection */ public WelcomeWizard(DdmsPreferenceStore store, boolean showInstallSdkPage, boolean showUsageOptinPage) { mStore = store; mShowWelcomePage = showInstallSdkPage; mShowUsagePage = showUsageOptinPage; setWindowTitle("Welcome to Android Development"); ImageDescriptor image = AdtPlugin.getImageDescriptor("icons/android-64.png"); //$NON-NLS-1$ setDefaultPageImageDescriptor(image); } @Override public void addPages() { if (mShowWelcomePage) { mWelcomePage = new WelcomeWizardPage(); addPage(mWelcomePage); } // It's possible that the user has already run the command line tools // such as ddms and has agreed to usage statistics collection, but has never // run ADT which is why the wizard was opened. No need to ask again. if (mShowUsagePage && !mStore.hasPingId()) { mUsagePage = new UsagePermissionPage(); addPage(mUsagePage); } } @Override public boolean performFinish() { if (mUsagePage != null) { boolean isUsageCollectionApproved = mUsagePage.isUsageCollectionApproved(); DdmsPreferenceStore store = new DdmsPreferenceStore(); // Workaround: Store a new ping id if one doesn't exist, regardless of // whether usage statistics gathering is enabled, to ensure that ddms and // ADT agree upon whether usage data collection is enabled. The reason this // is necessary is that the Eclipse PreferenceStore optimizes out writing // property values that equal their default values, and in our case, the // default value for usage-collection is "false", so it just doesn't write // it into the config file is the user opts out - which means that nothing // is written in ddms.config. That works in the sense that the getter returns // "usage collection"=false, but it doesn't work in the sense that it looks // like the property has not yet been decided by the user. DDMS will look at // the existence of a ping id to see whether we've already considered the // question, so do the same here. if (!store.hasPingId()) { store.generateNewPingId(); } store.setPingOptIn(isUsageCollectionApproved); } if (mWelcomePage != null) { // Read out wizard settings immediately; we will perform the actual work // after the wizard window has been taken down and it's too late to read the // settings then final File path = mWelcomePage.getPath(); final boolean installCommon = mWelcomePage.isInstallCommon(); final boolean installLatest = mWelcomePage.isInstallLatest(); final boolean createNew = mWelcomePage.isCreateNew(); // Perform installation asynchronously since it takes a while. getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (createNew) { try { Set<Integer> apiLevels = new HashSet<Integer>(); if (installCommon) { apiLevels.add(8); } if (installLatest) { apiLevels.add(AdtUpdateDialog.USE_MAX_REMOTE_API_LEVEL); } installSdk(path, apiLevels); } catch (Exception e) { AdtPlugin.logAndPrintError(e, "ADT Welcome Wizard", "Installation failed"); } } // Set SDK path after installation since this will trigger a SDK refresh. AdtPrefs.getPrefs().setSdkLocation(path); } }); } // The wizard always succeeds, even if installation fails or is aborted return true; } /** * Trigger the install window. It will connect to the repository, display * a confirmation window showing which packages are selected for install * and display a progress dialog during installation. */ private boolean installSdk(File path, Set<Integer> apiLevels) { if (!path.isDirectory()) { if (!path.mkdirs()) { AdtPlugin.logAndPrintError(null, "ADT Welcome Wizard", "Failed to create directory %1$s", path.getAbsolutePath()); return false; } } // Get a shell to use for the SDK installation. There are cases where getActiveShell // returns null so attempt to obtain it through other means. Display display = AdtPlugin.getDisplay(); Shell shell = display.getActiveShell(); if (shell == null) { IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); if (window != null) { shell = window.getShell(); } } boolean disposeShell = false; if (shell == null) { shell = new Shell(display); AdtPlugin.log(IStatus.WARNING, "No parent shell for SDK installation dialog"); disposeShell = true; } AdtUpdateDialog updater = new AdtUpdateDialog( shell, new AdtConsoleSdkLog(), path.getAbsolutePath()); // Note: we don't have to specify tools & platform-tools since they // are required dependencies of any platform. boolean result = updater.installNewSdk(apiLevels); // TODO: Install extra package here as well since it is now core to most of // the templates // if (result) { // updater.installExtraPackage(vendor, path); // } if (disposeShell) { shell.dispose(); } if (!result) { AdtPlugin.printErrorToConsole("Failed to install Android SDK."); return false; } return true; } }