1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.project; 18 19 import static com.android.SdkConstants.FQCN_GRID_LAYOUT; 20 import static com.android.SdkConstants.FQCN_GRID_LAYOUT_V7; 21 import static com.android.SdkConstants.FQCN_SPACE; 22 import static com.android.SdkConstants.FQCN_SPACE_V7; 23 24 import com.android.annotations.NonNull; 25 import com.android.annotations.Nullable; 26 import com.android.ide.eclipse.adt.AdtUtils; 27 import com.android.ide.eclipse.adt.internal.actions.AddSupportJarAction; 28 import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; 29 import com.android.ide.eclipse.adt.internal.sdk.ProjectState; 30 import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryState; 31 import com.android.ide.eclipse.adt.internal.sdk.Sdk; 32 33 import org.eclipse.core.resources.IProject; 34 import org.eclipse.jdt.core.IJavaProject; 35 import org.eclipse.jface.dialogs.MessageDialog; 36 import org.eclipse.swt.widgets.Display; 37 38 /** 39 * Helper class for the Android Support Library. The support library provides 40 * (for example) a backport of GridLayout, which must be used as a library 41 * project rather than a jar library since it has resources. This class provides 42 * support for finding the library project, or downloading and installing it on 43 * demand if it does not, as well as translating tags such as 44 * {@code <GridLayout>} into {@code <com.android.support.v7.GridLayout>} if it 45 * does not. 46 */ 47 public class SupportLibraryHelper { 48 /** 49 * Returns the correct tag to use for the given view tag. This is normally 50 * the same as the tag itself. However, for some views which are not available 51 * on all platforms, this will: 52 * <ul> 53 * <li> Check if the view is available in the compatibility library, 54 * and if so, if the support library is not installed, will offer to 55 * install it via the SDK manager. 56 * <li> (The tool may also offer to adjust the minimum SDK of the project 57 * up to a level such that the given tag is supported directly, and then 58 * this method will return the original tag.) 59 * <li> Check whether the compatibility library is included in the project, and 60 * if not, offer to copy it into the workspace and add a library dependency. 61 * <li> Return the alternative tag. For example, for "GridLayout", it will 62 * (if the minimum SDK is less than 14) return "com.android.support.v7.GridLayout" 63 * instead. 64 * </ul> 65 * 66 * @param project the project to add the dependency into 67 * @param tag the tag to look up, such as "GridLayout" 68 * @return the tag to use in the layout, normally the same as the input tag but possibly 69 * an equivalent compatibility library tag instead. 70 */ 71 @NonNull getTagFor(@onNull IProject project, @NonNull String tag)72 public static String getTagFor(@NonNull IProject project, @NonNull String tag) { 73 boolean isGridLayout = tag.equals(FQCN_GRID_LAYOUT); 74 boolean isSpace = tag.equals(FQCN_SPACE); 75 if (isGridLayout || isSpace) { 76 int minSdk = ManifestInfo.get(project).getMinSdkVersion(); 77 if (minSdk < 14) { 78 // See if the support library is installed in the SDK area 79 // See if there is a local project in the workspace providing the 80 // project 81 IProject supportProject = getSupportProjectV7(); 82 if (supportProject != null) { 83 // Make sure I have a dependency on it 84 ProjectState state = Sdk.getProjectState(project); 85 if (state != null) { 86 for (LibraryState library : state.getLibraries()) { 87 if (supportProject.equals(library.getProjectState().getProject())) { 88 // Found it: you have the compatibility library and have linked 89 // to it: use the alternative tag 90 return isGridLayout ? FQCN_GRID_LAYOUT_V7 : FQCN_SPACE_V7; 91 } 92 } 93 } 94 } 95 96 // Ask user to install it 97 String message = String.format( 98 "%1$s requires API level 14 or higher, or a compatibility " 99 + "library for older versions.\n\n" 100 + " Do you want to install the compatibility library?", tag); 101 MessageDialog dialog = 102 new MessageDialog( 103 Display.getCurrent().getActiveShell(), 104 "Warning", 105 null, 106 message, 107 MessageDialog.QUESTION, 108 new String[] { 109 "Install", "Cancel" 110 }, 111 1 /* default button: Cancel */); 112 int answer = dialog.open(); 113 if (answer == 0) { 114 if (supportProject != null) { 115 // Just add library dependency 116 if (!AddSupportJarAction.addLibraryDependency( 117 supportProject, 118 project, 119 true /* waitForFinish */)) { 120 return tag; 121 } 122 } else { 123 // Install library AND add dependency 124 if (!AddSupportJarAction.installGridLayoutLibrary( 125 project, 126 true /* waitForFinish */)) { 127 return tag; 128 } 129 } 130 131 return isGridLayout ? FQCN_GRID_LAYOUT_V7 : FQCN_SPACE_V7; 132 } 133 } 134 } 135 136 return tag; 137 } 138 139 /** Cache for {@link #getSupportProjectV7()} */ 140 private static IProject sCachedProject; 141 142 /** 143 * Finds and returns the support project in the workspace, if any. 144 * 145 * @return the android support library project, or null if not found 146 */ 147 @Nullable getSupportProjectV7()148 public static IProject getSupportProjectV7() { 149 if (sCachedProject != null) { 150 if (sCachedProject.isAccessible()) { 151 return sCachedProject; 152 } else { 153 sCachedProject = null; 154 } 155 } 156 157 sCachedProject = findSupportProjectV7(); 158 return sCachedProject; 159 } 160 161 @Nullable findSupportProjectV7()162 private static IProject findSupportProjectV7() { 163 for (IJavaProject javaProject : AdtUtils.getOpenAndroidProjects()) { 164 IProject project = javaProject.getProject(); 165 ProjectState state = Sdk.getProjectState(project); 166 if (state != null && state.isLibrary()) { 167 ManifestInfo manifestInfo = ManifestInfo.get(project); 168 if (manifestInfo.getPackage().equals("android.support.v7.gridlayout")) { //$NON-NLS-1$ 169 return project; 170 } 171 } 172 } 173 174 return null; 175 } 176 } 177