19bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye/* 29bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Copyright (C) 2011 The Android Open Source Project 39bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 49bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 59bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * you may not use this file except in compliance with the License. 69bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * You may obtain a copy of the License at 79bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 89bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * http://www.eclipse.org/org/documents/epl-v10.php 99bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 109bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Unless required by applicable law or agreed to in writing, software 119bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * distributed under the License is distributed on an "AS IS" BASIS, 129bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * See the License for the specific language governing permissions and 149bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * limitations under the License. 159bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 169bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 179bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyepackage com.android.ide.eclipse.adt.internal.editors.manifest; 189bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1912d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ANDROID_STYLE_RESOURCE_PREFIX; 2012d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.CLASS_ACTIVITY; 2181cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.SdkConstants.NS_RESOURCES; 2281cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.ATTRIBUTE_ICON; 2381cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.ATTRIBUTE_LABEL; 2481cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION; 2581cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.ATTRIBUTE_NAME; 2681cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.ATTRIBUTE_PACKAGE; 2781cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.ATTRIBUTE_TARGET_SDK_VERSION; 2881cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.ATTRIBUTE_THEME; 2981cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.NODE_ACTIVITY; 3081cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport static com.android.xml.AndroidManifest.NODE_USES_SDK; 319bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport static org.eclipse.jdt.core.search.IJavaSearchConstants.REFERENCES; 329bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 339bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbyeimport com.android.annotations.NonNull; 349bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbyeimport com.android.annotations.Nullable; 359bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport com.android.ide.eclipse.adt.AdtPlugin; 369bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; 379bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport com.android.ide.eclipse.adt.internal.sdk.Sdk; 389bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport com.android.ide.eclipse.adt.io.IFolderWrapper; 399bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport com.android.io.IAbstractFile; 4071ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbyeimport com.android.io.StreamException; 4147e918dd86afa699e017f498de3349a296e7a20fXavier Ducrohetimport com.android.resources.ScreenSize; 429bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport com.android.sdklib.IAndroidTarget; 4385e4a1a9dd133abb879ec211ce8dd385004edf22Xavier Ducrohetimport com.android.utils.Pair; 4481cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport com.android.xml.AndroidManifest; 459bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 469bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.resources.IFile; 479bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.resources.IProject; 489bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.resources.IResource; 499bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.resources.IWorkspace; 509bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.resources.ResourcesPlugin; 519bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.runtime.CoreException; 529bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.runtime.IPath; 539bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.runtime.NullProgressMonitor; 5457f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbyeimport org.eclipse.core.runtime.OperationCanceledException; 559bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.core.runtime.QualifiedName; 569bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.IField; 579bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.IJavaElement; 589bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.IJavaProject; 599bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.IMethod; 60d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbyeimport org.eclipse.jdt.core.IPackageFragment; 619bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.IPackageFragmentRoot; 629bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.IType; 63bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbyeimport org.eclipse.jdt.core.ITypeHierarchy; 649bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.search.IJavaSearchScope; 659bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.search.SearchEngine; 669bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.search.SearchMatch; 679bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.search.SearchParticipant; 689bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.search.SearchPattern; 699bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jdt.core.search.SearchRequestor; 70bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbyeimport org.eclipse.jdt.internal.core.BinaryType; 719bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.jface.text.IDocument; 729bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.ui.editors.text.TextFileDocumentProvider; 739bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.eclipse.ui.texteditor.IDocumentProvider; 749bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.w3c.dom.Document; 759bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.w3c.dom.Element; 769bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.w3c.dom.NodeList; 779bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.xml.sax.InputSource; 789bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport org.xml.sax.SAXException; 799bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 80bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbyeimport java.util.ArrayList; 817e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbyeimport java.util.Collections; 829bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport java.util.HashMap; 83bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbyeimport java.util.LinkedList; 849bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport java.util.List; 859bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport java.util.Map; 869bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport java.util.regex.Matcher; 879bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport java.util.regex.Pattern; 889bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 899bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport javax.xml.parsers.DocumentBuilder; 909bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyeimport javax.xml.parsers.DocumentBuilderFactory; 9171ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbyeimport javax.xml.xpath.XPathExpressionException; 929bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 939bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye/** 949bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Retrieves and caches manifest information such as the themes to be used for 959bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * a given activity. 969bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 979bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @see AndroidManifest 989bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 999bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbyepublic class ManifestInfo { 1009bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 1019bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * The maximum number of milliseconds to search for an activity in the codebase when 1029bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * attempting to associate layouts with activities in 1039bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * {@link #guessActivity(IFile, String)} 1049bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 1059bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private static final int SEARCH_TIMEOUT_MS = 3000; 1069bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1079bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private final IProject mProject; 1089bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private String mPackage; 1091032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye private String mManifestTheme; 1109bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private Map<String, String> mActivityThemes; 1119bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private IAbstractFile mManifestFile; 1129bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private long mLastModified; 1137dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye private long mLastChecked; 1147dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye private String mMinSdkName; 1159bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye private int mMinSdk; 1161032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye private int mTargetSdk; 117ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye private String mApplicationIcon; 118ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye private String mApplicationLabel; 1199bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1209bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 1219bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Qualified name for the per-project non-persistent property storing the 1229bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * {@link ManifestInfo} for this project 1239bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 1249bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye final static QualifiedName MANIFEST_FINDER = new QualifiedName(AdtPlugin.PLUGIN_ID, 1259bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye "manifest"); //$NON-NLS-1$ 1269bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1279bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 1289bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Constructs an {@link ManifestInfo} for the given project. Don't use this method; 1299bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * use the {@link #get} factory method instead. 1309bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 1319bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @param project project to create an {@link ManifestInfo} for 1329bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 1339bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private ManifestInfo(IProject project) { 1349bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mProject = project; 1359bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 1369bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1379bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 138140a4978947acc893356cbf06807e912588b3bdfTor Norbye * Clears the cached manifest information. The next get call on one of the 139140a4978947acc893356cbf06807e912588b3bdfTor Norbye * properties will cause the information to be refreshed. 140140a4978947acc893356cbf06807e912588b3bdfTor Norbye */ 141140a4978947acc893356cbf06807e912588b3bdfTor Norbye public void clear() { 142140a4978947acc893356cbf06807e912588b3bdfTor Norbye mLastChecked = 0; 143140a4978947acc893356cbf06807e912588b3bdfTor Norbye } 144140a4978947acc893356cbf06807e912588b3bdfTor Norbye 145140a4978947acc893356cbf06807e912588b3bdfTor Norbye /** 1469bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Returns the {@link ManifestInfo} for the given project 1479bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 1489bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @param project the project the finder is associated with 1499bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @return a {@ManifestInfo} for the given project, never null 1509bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 1519bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @NonNull 1529bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public static ManifestInfo get(IProject project) { 1539bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye ManifestInfo finder = null; 1549bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye try { 1559bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye finder = (ManifestInfo) project.getSessionProperty(MANIFEST_FINDER); 1569bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } catch (CoreException e) { 1579bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // Not a problem; we will just create a new one 1589bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 1599bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1609bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (finder == null) { 1619bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye finder = new ManifestInfo(project); 1629bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye try { 1639bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye project.setSessionProperty(MANIFEST_FINDER, finder); 1649bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } catch (CoreException e) { 1659bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye AdtPlugin.log(e, "Can't store ManifestInfo"); 1669bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 1679bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 1689bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1699bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return finder; 1709bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 1719bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1729bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 1739bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Ensure that the package, theme and activity maps are initialized and up to date 1749bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * with respect to the manifest file 1759bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 1769bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private void sync() { 1777dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye // Since each of the accessors call sync(), allow a bunch of immediate 1787dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye // accessors to all bypass the file stat() below 1797dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye long now = System.currentTimeMillis(); 1807dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye if (now - mLastChecked < 50 && mManifestFile != null) { 1817dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye return; 1827dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye } 1837dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye mLastChecked = now; 184bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye 1859bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (mManifestFile == null) { 1869bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IFolderWrapper projectFolder = new IFolderWrapper(mProject); 1879bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mManifestFile = AndroidManifest.getManifest(projectFolder); 1889bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (mManifestFile == null) { 1899bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return; 1909bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 1919bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 1929bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 1939bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // Check to see if our data is up to date 1949bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye long fileModified = mManifestFile.getModificationStamp(); 1959bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (fileModified == mLastModified) { 1969bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // Already have up to date data 1979bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return; 1989bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 1999bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mLastModified = fileModified; 2009bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 2019bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mActivityThemes = new HashMap<String, String>(); 2021032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye mManifestTheme = null; 2031032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye mTargetSdk = 1; // Default when not specified 2049bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye mMinSdk = 1; // Default when not specified 205140a4978947acc893356cbf06807e912588b3bdfTor Norbye mMinSdkName = "1"; // Default when not specified 2069bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mPackage = ""; //$NON-NLS-1$ 207ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye mApplicationIcon = null; 208ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye mApplicationLabel = null; 2091032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye 2109bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye Document document = null; 2119bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye try { 2129bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 2139bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye InputSource is = new InputSource(mManifestFile.getContents()); 2149bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 2159bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye factory.setNamespaceAware(true); 2169bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye factory.setValidating(false); 2179bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye DocumentBuilder builder = factory.newDocumentBuilder(); 2189bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye document = builder.parse(is); 2199bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 2209bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye Element root = document.getDocumentElement(); 2219bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mPackage = root.getAttribute(ATTRIBUTE_PACKAGE); 2229bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye NodeList activities = document.getElementsByTagName(NODE_ACTIVITY); 2239bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye for (int i = 0, n = activities.getLength(); i < n; i++) { 2249bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye Element activity = (Element) activities.item(i); 2259bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye String theme = activity.getAttributeNS(NS_RESOURCES, ATTRIBUTE_THEME); 2269bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (theme != null && theme.length() > 0) { 2279bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye String name = activity.getAttributeNS(NS_RESOURCES, ATTRIBUTE_NAME); 2289bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (name.startsWith(".") //$NON-NLS-1$ 2299bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye && mPackage != null && mPackage.length() > 0) { 2309bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye name = mPackage + name; 2319bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 2329bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mActivityThemes.put(name, theme); 2339bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 2349bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 2359bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 236ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye NodeList applications = root.getElementsByTagName(AndroidManifest.NODE_APPLICATION); 237ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye if (applications.getLength() > 0) { 238ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye assert applications.getLength() == 1; 239ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye Element application = (Element) applications.item(0); 240ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye if (application.hasAttributeNS(NS_RESOURCES, ATTRIBUTE_ICON)) { 241ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye mApplicationIcon = application.getAttributeNS(NS_RESOURCES, ATTRIBUTE_ICON); 242ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye } 243ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye if (application.hasAttributeNS(NS_RESOURCES, ATTRIBUTE_LABEL)) { 244ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye mApplicationLabel = application.getAttributeNS(NS_RESOURCES, ATTRIBUTE_LABEL); 245ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye } 2464a5bddd1c70b6a6a8197d1868d0159f80a0fde77Tor Norbye 24734230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye String defaultTheme = application.getAttributeNS(NS_RESOURCES, ATTRIBUTE_THEME); 24834230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye if (defaultTheme != null && !defaultTheme.isEmpty()) { 24934230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye // From manifest theme documentation: 25034230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye // "If that attribute is also not set, the default system theme is used." 25134230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye mManifestTheme = defaultTheme; 25234230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye } 253ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye } 254ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye 2559bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // Look up target SDK 25634230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye NodeList usesSdks = root.getElementsByTagName(NODE_USES_SDK); 25734230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye if (usesSdks.getLength() > 0) { 25834230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye Element usesSdk = (Element) usesSdks.item(0); 25934230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye mMinSdk = getApiVersion(usesSdk, ATTRIBUTE_MIN_SDK_VERSION, 1); 26034230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye mTargetSdk = getApiVersion(usesSdk, ATTRIBUTE_TARGET_SDK_VERSION, mMinSdk); 2619bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 26234230d8dd05143b85d520f5e34a5ea4f055e0e96Tor Norbye 2639bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } catch (SAXException e) { 2649bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye AdtPlugin.log(e, "Malformed manifest"); 2659bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } catch (Exception e) { 2669bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye AdtPlugin.log(e, "Could not read Manifest data"); 2679bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 2689bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 2699bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 2707dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye private int getApiVersion(Element usesSdk, String attribute, int defaultApiLevel) { 2719bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye String valueString = null; 2729bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye if (usesSdk.hasAttributeNS(NS_RESOURCES, attribute)) { 2739bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye valueString = usesSdk.getAttributeNS(NS_RESOURCES, attribute); 274140a4978947acc893356cbf06807e912588b3bdfTor Norbye if (attribute.equals(ATTRIBUTE_MIN_SDK_VERSION)) { 275140a4978947acc893356cbf06807e912588b3bdfTor Norbye mMinSdkName = valueString; 276140a4978947acc893356cbf06807e912588b3bdfTor Norbye } 2779bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } 2789bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye 2799bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye if (valueString != null) { 2809bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye int apiLevel = -1; 2819bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye try { 2829bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye apiLevel = Integer.valueOf(valueString); 2839bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } catch (NumberFormatException e) { 2849bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye // Handle codename 2859bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye if (Sdk.getCurrent() != null) { 2869bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye IAndroidTarget target = Sdk.getCurrent().getTargetFromHashString( 2879bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye "android-" + valueString); //$NON-NLS-1$ 2889bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye if (target != null) { 2899bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye // codename future API level is current api + 1 2909bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye apiLevel = target.getVersion().getApiLevel() + 1; 2919bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } 2929bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } 2939bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } 2949bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye 2959bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye return apiLevel; 2969bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } 2979bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye 2989bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye return defaultApiLevel; 2999bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } 3009bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye 3019bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 3029bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Returns the default package registered in the Android manifest 3039bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 3049bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @return the default package registered in the manifest 3059bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 3069bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @NonNull 3079bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public String getPackage() { 3089bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye sync(); 3099bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return mPackage; 3109bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 3119bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 3129bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 3139bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Returns a map from activity full class names to the corresponding theme style to be 3149bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * used 3159bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 3169bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @return a map from activity fqcn to theme style 3179bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 3189bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @NonNull 3199bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public Map<String, String> getActivityThemes() { 3209bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye sync(); 3219bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return mActivityThemes; 3229bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 3239bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 3249bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 325bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * Returns the manifest theme registered on the application, if any 326bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * 327bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * @return a manifest theme, or null if none was registered 328bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye */ 329bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye @Nullable 3307dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye public String getManifestTheme() { 331bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye sync(); 332bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye return mManifestTheme; 333bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 334bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye 335bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye /** 3369bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Returns the default theme for this project, by looking at the manifest default 3371032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye * theme registration, target SDK, rendering target, etc. 3389bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 3391032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye * @param renderingTarget the rendering target use to render the theme, or null 3409bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @param screenSize the screen size to obtain a default theme for, or null if unknown 3419bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @return the theme to use for this project, never null 3429bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 3439bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @NonNull 34447e918dd86afa699e017f498de3349a296e7a20fXavier Ducrohet public String getDefaultTheme(IAndroidTarget renderingTarget, ScreenSize screenSize) { 3459bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye sync(); 3469bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 3471032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye if (mManifestTheme != null) { 3481032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye return mManifestTheme; 3491032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye } 3501032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye 3511032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye int renderingTargetSdk = mTargetSdk; 3521032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye if (renderingTarget != null) { 3531032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye renderingTargetSdk = renderingTarget.getVersion().getApiLevel(); 3541032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye } 3551032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye 3561032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye int apiLevel = Math.min(mTargetSdk, renderingTargetSdk); 3571032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye // For now this theme works only on XLARGE screens. When it works for all sizes, 3581032d1fc8b5fbc3f8b472505d6b2d9f82741c3e1Tor Norbye // add that new apiLevel to this check. 3594a5bddd1c70b6a6a8197d1868d0159f80a0fde77Tor Norbye if (apiLevel >= 11 && screenSize == ScreenSize.XLARGE || apiLevel >= 14) { 36012d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye return ANDROID_STYLE_RESOURCE_PREFIX + "Theme.Holo"; //$NON-NLS-1$ 3619bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } else { 36212d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye return ANDROID_STYLE_RESOURCE_PREFIX + "Theme"; //$NON-NLS-1$ 3639bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 3649bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 3659bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 3669bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 367ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye * Returns the application icon, or null 368ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye * 369ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye * @return the application icon, or null 370ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye */ 3719bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @Nullable 372ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye public String getApplicationIcon() { 373ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye sync(); 374ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye return mApplicationIcon; 375ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye } 376ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye 377ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye /** 378ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye * Returns the application label, or null 379ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye * 380ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye * @return the application label, or null 381ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye */ 3829bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @Nullable 383ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye public String getApplicationLabel() { 384ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye sync(); 385ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye return mApplicationLabel; 386ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye } 387ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye 388ab02e0845abebb9dd36e6e3cf9a2b5ecfb34bdaaTor Norbye /** 3899bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * Returns the target SDK version 3909bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * 3919bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * @return the target SDK version 3929bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye */ 3939bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye public int getTargetSdkVersion() { 3949bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye sync(); 3959bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye return mTargetSdk; 3969bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } 3979bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye 3989bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye /** 3999bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * Returns the minimum SDK version 4009bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * 4019bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * @return the minimum SDK version 4029bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye */ 4039bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye public int getMinSdkVersion() { 4049bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye sync(); 4059bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye return mMinSdk; 4069bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye } 4079bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye 4089bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye /** 4097dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye * Returns the minimum SDK version name (which may not be a numeric string, e.g. 410140a4978947acc893356cbf06807e912588b3bdfTor Norbye * it could be a codename). It will never be null or empty; if no min sdk version 411140a4978947acc893356cbf06807e912588b3bdfTor Norbye * was specified in the manifest, the return value will be "1". Use 4122e3527410003859ee6bcb3a2971d72bcfdbcc829Tor Norbye * {@link #getMinSdkCodeName()} instead if you want to look up whether there is a code name. 4137dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye * 4147dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye * @return the minimum SDK version 4157dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye */ 416140a4978947acc893356cbf06807e912588b3bdfTor Norbye @NonNull 4177dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye public String getMinSdkName() { 4187dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye sync(); 419140a4978947acc893356cbf06807e912588b3bdfTor Norbye if (mMinSdkName == null || mMinSdkName.isEmpty()) { 420140a4978947acc893356cbf06807e912588b3bdfTor Norbye mMinSdkName = "1"; //$NON-NLS-1$ 421140a4978947acc893356cbf06807e912588b3bdfTor Norbye } 422140a4978947acc893356cbf06807e912588b3bdfTor Norbye 4237dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye return mMinSdkName; 4247dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye } 4257dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye 4267dd444ea0125e50a5e88604afb6de43e80b7c270Tor Norbye /** 427140a4978947acc893356cbf06807e912588b3bdfTor Norbye * Returns the code name used for the minimum SDK version, if any. 428140a4978947acc893356cbf06807e912588b3bdfTor Norbye * 429140a4978947acc893356cbf06807e912588b3bdfTor Norbye * @return the minSdkVersion codename or null 430140a4978947acc893356cbf06807e912588b3bdfTor Norbye */ 431140a4978947acc893356cbf06807e912588b3bdfTor Norbye @Nullable 432140a4978947acc893356cbf06807e912588b3bdfTor Norbye public String getMinSdkCodeName() { 433140a4978947acc893356cbf06807e912588b3bdfTor Norbye String minSdkName = getMinSdkName(); 434140a4978947acc893356cbf06807e912588b3bdfTor Norbye if (!Character.isDigit(minSdkName.charAt(0))) { 435140a4978947acc893356cbf06807e912588b3bdfTor Norbye return minSdkName; 436140a4978947acc893356cbf06807e912588b3bdfTor Norbye } 437140a4978947acc893356cbf06807e912588b3bdfTor Norbye 438140a4978947acc893356cbf06807e912588b3bdfTor Norbye return null; 439140a4978947acc893356cbf06807e912588b3bdfTor Norbye } 440140a4978947acc893356cbf06807e912588b3bdfTor Norbye 441140a4978947acc893356cbf06807e912588b3bdfTor Norbye /** 442d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye * Returns the {@link IPackageFragment} for the package registered in the manifest 443d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye * 444d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye * @return the {@link IPackageFragment} for the package registered in the manifest 445d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye */ 4469bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @Nullable 447d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye public IPackageFragment getPackageFragment() { 448d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye sync(); 449d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye try { 450d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye IJavaProject javaProject = BaseProjectHelper.getJavaProject(mProject); 451d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye if (javaProject != null) { 452d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye IPackageFragmentRoot root = ManifestInfo.getSourcePackageRoot(javaProject); 453d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye if (root != null) { 454d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye return root.getPackageFragment(mPackage); 455d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye } 456d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye } 457d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye } catch (CoreException e) { 458d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye AdtPlugin.log(e, null); 459d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye } 460d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye 461d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye return null; 462d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye } 463d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye 464d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye /** 4659bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Returns the activity associated with the given layout file. Makes an educated guess 4669bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * by peeking at the usages of the R.layout.name field corresponding to the layout and 4679bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * if it finds a usage. 4689bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 4699bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @param project the project containing the layout 4709bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @param layoutName the layout whose activity we want to look up 4719bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @param pkg the package containing activities 4729bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @return the activity name 4739bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 4749bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @Nullable 4759bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public static String guessActivity(IProject project, String layoutName, String pkg) { 476bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye List<String> activities = guessActivities(project, layoutName, pkg); 477bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye if (activities.size() > 0) { 478bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye return activities.get(0); 479bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } else { 480bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye return null; 481bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 482bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 483bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye 484bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye /** 485bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * Returns the activities associated with the given layout file. Makes an educated guess 486bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * by peeking at the usages of the R.layout.name field corresponding to the layout and 487bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * if it finds a usage. 488bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * 489bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * @param project the project containing the layout 490bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * @param layoutName the layout whose activity we want to look up 491bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * @param pkg the package containing activities 492bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * @return the activity name 493bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye */ 494bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye @NonNull 495bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye public static List<String> guessActivities(IProject project, String layoutName, String pkg) { 496bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye final LinkedList<String> activities = new LinkedList<String>(); 4979bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye SearchRequestor requestor = new SearchRequestor() { 4989bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye @Override 4999bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public void acceptSearchMatch(SearchMatch match) throws CoreException { 5009bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye Object element = match.getElement(); 5019bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (element instanceof IMethod) { 5029bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IMethod method = (IMethod) element; 5039bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IType declaringType = method.getDeclaringType(); 5049bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye String fqcn = declaringType.getFullyQualifiedName(); 505bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye 506bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye if ((declaringType.getSuperclassName() != null && 507bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye declaringType.getSuperclassName().endsWith("Activity")) //$NON-NLS-1$ 508bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye || method.getElementName().equals("onCreate")) { //$NON-NLS-1$ 509bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye activities.addFirst(fqcn); 510bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } else { 511bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye activities.addLast(fqcn); 5129bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5139bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5149bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5159bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye }; 5169bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye try { 5179bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IJavaProject javaProject = BaseProjectHelper.getJavaProject(project); 5189bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (javaProject == null) { 5197e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye return Collections.emptyList(); 5209bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5219bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // TODO - look around a bit more and see if we can figure out whether the 5229bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // call if from within a setContentView call! 5239bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 5249bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // Search for which java classes call setContentView(R.layout.layoutname); 5259bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye String typeFqcn = "R.layout"; //$NON-NLS-1$ 5269bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (pkg != null) { 5279bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye typeFqcn = pkg + '.' + typeFqcn; 5289bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5299bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 5309bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IType type = javaProject.findType(typeFqcn); 5319bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (type != null) { 5329bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IField field = type.getField(layoutName); 5339bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (field.exists()) { 5349bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye SearchPattern pattern = SearchPattern.createPattern(field, REFERENCES); 53557f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye try { 53657f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye search(requestor, javaProject, pattern); 53757f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye } catch (OperationCanceledException canceled) { 53857f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye // pass 53957f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye } 5409bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5419bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5429bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } catch (CoreException e) { 5439bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye AdtPlugin.log(e, null); 5449bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5459bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 546bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye return activities; 5479bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 5489bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 5499bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 550bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * Returns all activities found in the given project (including those in libraries, 551bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * except for android.jar itself) 552bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * 553bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * @param project the project 554bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye * @return a list of activity classes as fully qualified class names 555bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye */ 556bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye @SuppressWarnings("restriction") // BinaryType 557bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye @NonNull 558bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye public static List<String> getProjectActivities(IProject project) { 559bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye final List<String> activities = new ArrayList<String>(); 560bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye try { 561bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye final IJavaProject javaProject = BaseProjectHelper.getJavaProject(project); 562bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye if (javaProject != null) { 563bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye IType[] activityTypes = new IType[0]; 56412d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye IType activityType = javaProject.findType(CLASS_ACTIVITY); 565bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye if (activityType != null) { 566bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye ITypeHierarchy hierarchy = 567bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye activityType.newTypeHierarchy(javaProject, new NullProgressMonitor()); 568bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye activityTypes = hierarchy.getAllSubtypes(activityType); 569bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye for (IType type : activityTypes) { 570bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye if (type instanceof BinaryType && (type.getClassFile() == null 571bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye || type.getClassFile().getResource() == null)) { 572bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye continue; 573bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 574bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye activities.add(type.getFullyQualifiedName()); 575bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 576bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 577bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 578bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } catch (CoreException e) { 579bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye AdtPlugin.log(e, null); 580bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 581bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye 582bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye return activities; 583bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye } 584bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye 585bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye 586bc5879056fba2eb616dea06e6191bdc218b594c0Tor Norbye /** 5879bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Returns the activity associated with the given layout file. 5889bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * <p> 5899bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * This is an alternative to {@link #guessActivity(IFile, String)}. Whereas 5909bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * guessActivity simply looks for references to "R.layout.foo", this method searches 5919bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * for all usages of Activity#setContentView(int), and for each match it looks up the 5929bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * corresponding call text (such as "setContentView(R.layout.foo)"). From this it uses 5939bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * a regexp to pull out "foo" from this, and stores the association that layout "foo" 5949bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * is associated with the activity class that contained the setContentView call. 5959bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * <p> 5969bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * This has two potential advantages: 5979bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * <ol> 5989bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * <li>It can be faster. We do the reference search -once-, and we've built a map of 5999bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * all the layout-to-activity mappings which we can then immediately look up other 6009bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * layouts for, which is particularly useful at startup when we have to compute the 6019bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * layout activity associations to populate the theme choosers. 6029bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * <li>It can be more accurate. Just because an activity references an "R.layout.foo" 6039bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * field doesn't mean it's setting it as a content view. 6049bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * </ol> 6059bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * However, this second advantage is also its chief problem. There are some common 6069bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * code constructs which means that the associated layout is not explicitly referenced 6079bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * in a direct setContentView call; on a couple of sample projects I tested I found 6089bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * patterns like for example "setContentView(v)" where "v" had been computed earlier. 6099bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Therefore, for now we're going to stick with the more general approach of just 6109bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * looking up each field when needed. We're keeping the code around, though statically 6119bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * compiled out with the "if (false)" construct below in case we revisit this. 6129bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * 6139bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @param layoutFile the layout whose activity we want to look up 6149bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * @return the activity name 6159bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 6169bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye @SuppressWarnings("all") 6179bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @Nullable 6189bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public String guessActivityBySetContentView(String layoutName) { 6199bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (false) { 6209bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // These should be fields 6219bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye final Pattern LAYOUT_FIELD_PATTERN = 6229bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye Pattern.compile("R\\.layout\\.([a-z0-9_]+)"); //$NON-NLS-1$ 6239bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye Map<String, String> mUsages = null; 6249bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 6259bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye sync(); 6269bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (mUsages == null) { 6279bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye final Map<String, String> usages = new HashMap<String, String>(); 6289bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mUsages = usages; 6299bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye SearchRequestor requestor = new SearchRequestor() { 6309bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye @Override 6319bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public void acceptSearchMatch(SearchMatch match) throws CoreException { 6329bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye Object element = match.getElement(); 6339bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (element instanceof IMethod) { 6349bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IMethod method = (IMethod) element; 6359bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IType declaringType = method.getDeclaringType(); 6369bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye String fqcn = declaringType.getFullyQualifiedName(); 6379bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IDocumentProvider provider = new TextFileDocumentProvider(); 6389bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IResource resource = match.getResource(); 6399bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye try { 6409bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye provider.connect(resource); 6419bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IDocument document = provider.getDocument(resource); 6429bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (document != null) { 6439bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye String matchText = document.get(match.getOffset(), 6449bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye match.getLength()); 6459bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye Matcher matcher = LAYOUT_FIELD_PATTERN.matcher(matchText); 6469bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (matcher.find()) { 6479bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye usages.put(matcher.group(1), fqcn); 6489bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6499bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6509bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } catch (Exception e) { 6519bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye AdtPlugin.log(e, "Can't find range information for %1$s", 6529bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye resource.getName()); 6539bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } finally { 6549bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye provider.disconnect(resource); 6559bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6569bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6579bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6589bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye }; 6599bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye try { 6609bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IJavaProject javaProject = BaseProjectHelper.getJavaProject(mProject); 6619bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (javaProject == null) { 6629bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return null; 6639bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6649bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 6659bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // Search for which java classes call setContentView(R.layout.layoutname); 6669bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye String typeFqcn = "R.layout"; //$NON-NLS-1$ 6679bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (mPackage != null) { 6689bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye typeFqcn = mPackage + '.' + typeFqcn; 6699bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6709bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 67112d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye IType activityType = javaProject.findType(CLASS_ACTIVITY); 6729bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (activityType != null) { 6739bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IMethod method = activityType.getMethod( 6749bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye "setContentView", new String[] {"I"}); //$NON-NLS-1$ //$NON-NLS-2$ 6759bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (method.exists()) { 6769bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye SearchPattern pattern = SearchPattern.createPattern(method, 6779bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye REFERENCES); 6789bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye search(requestor, javaProject, pattern); 6799bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6809bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6819bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } catch (CoreException e) { 6829bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye AdtPlugin.log(e, null); 6839bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6849bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6859bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 6869bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return mUsages.get(layoutName); 6879bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6889bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 6899bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return null; 6909bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 6919bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 6929bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** 6939bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * Performs a search using the given pattern, scope and handler. The search will abort 6949bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye * if it takes longer than {@link #SEARCH_TIMEOUT_MS} milliseconds. 6959bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye */ 6969bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private static void search(SearchRequestor requestor, IJavaProject javaProject, 6979bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye SearchPattern pattern) throws CoreException { 6989bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // Find the package fragment specified in the manifest; the activities should 6999bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye // live there. 7009bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IJavaSearchScope scope = createPackageScope(javaProject); 7019bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 7029bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye SearchParticipant[] participants = new SearchParticipant[] { 7039bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye SearchEngine.getDefaultSearchParticipant() 7049bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye }; 7059bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye SearchEngine engine = new SearchEngine(); 7069bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 7079bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye final long searchStart = System.currentTimeMillis(); 7089bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye NullProgressMonitor monitor = new NullProgressMonitor() { 7099bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private boolean mCancelled; 7109bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye @Override 7119bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public void internalWorked(double work) { 7129bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye long searchEnd = System.currentTimeMillis(); 7139bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (searchEnd - searchStart > SEARCH_TIMEOUT_MS) { 7149bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye mCancelled = true; 7159bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7169bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7179bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 7189bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye @Override 7199bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye public boolean isCanceled() { 7209bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return mCancelled; 7219bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7229bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye }; 7239bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye engine.search(pattern, participants, scope, requestor, monitor); 7249bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7259bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 7269bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye /** Creates a package search scope for the first package root in the given java project */ 7279bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye private static IJavaSearchScope createPackageScope(IJavaProject javaProject) { 7289bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IPackageFragmentRoot packageRoot = getSourcePackageRoot(javaProject); 7299bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 7309bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IJavaSearchScope scope; 7319bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (packageRoot != null) { 7329bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IJavaElement[] scopeElements = new IJavaElement[] { packageRoot }; 7339bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye scope = SearchEngine.createJavaSearchScope(scopeElements); 7349bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } else { 735b3ab7ef8a24a64bcd6f347e8e03bc647c12eb24bTor Norbye scope = SearchEngine.createWorkspaceScope(); 7369bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7379bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return scope; 7389bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7399bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 7409bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye /** 7419bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * Returns the first package root for the given java project 7429bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * 7439bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * @param javaProject the project to search in 7449bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * @return the first package root, or null 7459bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye */ 7469bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @Nullable 747d9cceddf012ef3284cf939773edc7b6e291fba21Tor Norbye public static IPackageFragmentRoot getSourcePackageRoot(IJavaProject javaProject) { 7489bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IPackageFragmentRoot packageRoot = null; 7499bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye List<IPath> sources = BaseProjectHelper.getSourceClasspaths(javaProject); 7509bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye 7519bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IWorkspace workspace = ResourcesPlugin.getWorkspace(); 7529bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye for (IPath path : sources) { 7539bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye IResource firstSource = workspace.getRoot().findMember(path); 7549bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (firstSource != null) { 7559bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye packageRoot = javaProject.getPackageFragmentRoot(firstSource); 7569bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye if (packageRoot != null) { 7579bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye break; 7589bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7599bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7609bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 7619bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye return packageRoot; 7629bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye } 76371ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye 76471ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye /** 76571ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye * Computes the minimum SDK and target SDK versions for the project 76671ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye * 7679bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye * @param project the project to look up the versions for 76871ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye * @return a pair of (minimum SDK, target SDK) versions, never null 76971ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye */ 7709bfb05e9d9ea4b2b969e50c3096e2fdb95653648Tor Norbye @NonNull 77171ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye public static Pair<Integer, Integer> computeSdkVersions(IProject project) { 77271ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye int mMinSdkVersion = 1; 77371ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye int mTargetSdkVersion = 1; 77471ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye 77571ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye IAbstractFile manifestFile = AndroidManifest.getManifest(new IFolderWrapper(project)); 77671ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye if (manifestFile != null) { 77771ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye try { 77871ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye Object value = AndroidManifest.getMinSdkVersion(manifestFile); 77971ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye mMinSdkVersion = 1; // Default case if missing 78071ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye if (value instanceof Integer) { 78171ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye mMinSdkVersion = ((Integer) value).intValue(); 78271ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } else if (value instanceof String) { 78371ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye // handle codename, only if we can resolve it. 78471ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye if (Sdk.getCurrent() != null) { 78571ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye IAndroidTarget target = Sdk.getCurrent().getTargetFromHashString( 78671ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye "android-" + value); //$NON-NLS-1$ 78771ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye if (target != null) { 78871ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye // codename future API level is current api + 1 78971ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye mMinSdkVersion = target.getVersion().getApiLevel() + 1; 79071ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } 79171ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } 79271ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } 79371ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye 79471ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye Integer i = AndroidManifest.getTargetSdkVersion(manifestFile); 79571ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye if (i == null) { 79671ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye mTargetSdkVersion = mMinSdkVersion; 79771ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } else { 79871ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye mTargetSdkVersion = i.intValue(); 79971ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } 80071ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } catch (XPathExpressionException e) { 80171ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye // do nothing we'll use 1 below. 80271ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } catch (StreamException e) { 80371ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye // do nothing we'll use 1 below. 80471ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } 80571ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } 80671ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye 80771ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye return Pair.of(mMinSdkVersion, mTargetSdkVersion); 80871ca2b70f4c4d463be013ebf643d363b92ebd5f7Tor Norbye } 8099bd5e125506d94855fa7f8dff917f20e1b4edb0bTor Norbye} 810