diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties
index 9336260646ca..1ab856936ffa 100644
--- a/plugins/android/resources/messages/AndroidBundle.properties
+++ b/plugins/android/resources/messages/AndroidBundle.properties
@@ -214,4 +214,7 @@ android.run.configuration.logcat.tab.title=Logcat
android.facet.settings.apk.path.label=APK path:
android.run.confguration.deploy.and.install.check.box=Deplo&y application
android.manifest.debuggable.attribute.not.true.warning=The manifest 'debuggable' attribute isn't set to 'true'.\nYou have to set it to true in order to debug on a device.\nWould you like to do it?
-android.logcat.no.android.facets.error=There is no Android facets in the project
\ No newline at end of file
+android.logcat.no.android.facets.error=There is no Android facets in the project
+android.facet.compiler.settings.manifest.title=Manifest
+android.facet.settings.compiler.manifest.from.structure=Use AndroidManifest.xml file specified at "Structure" section
+android.facet.settings.compiler.manifest.use.custom=Use custom manifest file:
\ No newline at end of file
diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java
index f54ecf418262..41882f0b06fa 100644
--- a/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java
+++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java
@@ -254,15 +254,16 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
if (target != null) {
AndroidCompileUtil.createSourceRootIfNotExist(sourceRootPath, module);
String assetsDirPath = assetsDir != null ? assetsDir.getPath() : null;
- VirtualFile manifestFile = AndroidRootUtil.getManifestFile(module);
- assert manifestFile != null;
- String manifestPath = manifestFile.getPath();
- items.add(new AptGenerationItem(module, manifestPath, resPaths, assetsDirPath, sourceRootPath, target,
- packageName, false));
-
- for (String libPackage : AndroidUtils.getDepLibsPackages(module)) {
+ VirtualFile manifestFile = AndroidRootUtil.getManifestFileForCompiler(facet);
+ if (manifestFile != null) {
+ String manifestPath = manifestFile.getPath();
items.add(new AptGenerationItem(module, manifestPath, resPaths, assetsDirPath, sourceRootPath, target,
- libPackage, true));
+ packageName, false));
+
+ for (String libPackage : AndroidUtils.getDepLibsPackages(module)) {
+ items.add(new AptGenerationItem(module, manifestPath, resPaths, assetsDirPath, sourceRootPath, target,
+ libPackage, true));
+ }
}
}
}
diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java
index dd54fb126649..e3d2a7790615 100644
--- a/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java
+++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java
@@ -92,7 +92,7 @@ public class AndroidPackagingCompiler implements PackagingCompiler {
for (Module module : affectedModules) {
AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null && !facet.getConfiguration().LIBRARY_PROJECT) {
- VirtualFile manifestFile = AndroidRootUtil.getManifestFile(module);
+ VirtualFile manifestFile = AndroidRootUtil.getManifestFileForCompiler(facet);
VirtualFile[] sourceRoots = getSourceRootsForModuleAndDependencies(module);
if (manifestFile != null) {
AndroidFacetConfiguration configuration = facet.getConfiguration();
diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidResourcesPackagingCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidResourcesPackagingCompiler.java
index d0a94b84760b..699cc023ff29 100644
--- a/plugins/android/src/org/jetbrains/android/compiler/AndroidResourcesPackagingCompiler.java
+++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidResourcesPackagingCompiler.java
@@ -45,7 +45,7 @@ public class AndroidResourcesPackagingCompiler implements ClassPostProcessingCom
for (Module module : affectedModules) {
AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null && !facet.getConfiguration().LIBRARY_PROJECT) {
- VirtualFile manifestFile = AndroidRootUtil.getManifestFile(module);
+ VirtualFile manifestFile = AndroidRootUtil.getManifestFileForCompiler(facet);
VirtualFile assetsDir = AndroidRootUtil.getAssetsDir(module);
if (manifestFile != null) {
AndroidFacetConfiguration configuration = facet.getConfiguration();
diff --git a/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java b/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java
index af773936be4c..93a0d69ee056 100644
--- a/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java
+++ b/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java
@@ -49,7 +49,7 @@ public class ResourcesValidityState implements ValidityState {
IAndroidTarget target = platform != null ? platform.getTarget() : null;
myAndroidTargetName = target != null ? target.getFullName() : "";
- VirtualFile manifestFile = AndroidRootUtil.getManifestFile(module);
+ VirtualFile manifestFile = AndroidRootUtil.getManifestFileForCompiler(facet);
if (manifestFile != null) {
myResourceTimestamps.put(manifestFile.getPath(), manifestFile.getTimeStamp());
}
@@ -58,7 +58,7 @@ public class ResourcesValidityState implements ValidityState {
collectFiles(resourcesDir);
}
for (AndroidFacet depFacet : AndroidUtils.getAllAndroidDependencies(module, true)) {
- VirtualFile depManifest = AndroidRootUtil.getManifestFile(depFacet.getModule());
+ VirtualFile depManifest = AndroidRootUtil.getManifestFileForCompiler(depFacet);
if (depManifest != null) {
myResourceTimestamps.put(depManifest.getPath(), depManifest.getTimeStamp());
}
diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
index 2127535251f6..9cc8d2e7309f 100644
--- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
+++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
@@ -57,6 +57,9 @@ public class AndroidFacetConfiguration implements FacetConfiguration {
public boolean USE_CUSTOM_APK_RESOURCE_FOLDER = false;
public String CUSTOM_APK_RESOURCE_FOLDER = "";
+ public boolean USE_CUSTOM_COMPILER_MANIFEST = false;
+ public String CUSTOM_COMPILER_MANIFEST = "";
+
public String APK_PATH = "";
public boolean ADD_ANDROID_LIBRARY = true;
diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form
index 76cbc0dc0bbd..cc727652b412 100644
--- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form
+++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form
@@ -3,7 +3,7 @@
-
+
@@ -176,7 +176,7 @@
-
+
@@ -187,7 +187,7 @@
-
+
@@ -227,7 +227,7 @@
-
+
@@ -259,7 +259,7 @@
-
+
@@ -312,7 +312,7 @@
-
+
@@ -323,6 +323,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -342,5 +375,9 @@
+
+
+
+
diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java
index 6ca0c770a7a8..a2e8b416cae3 100644
--- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java
+++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java
@@ -103,6 +103,9 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
private JCheckBox myGenerateUnsignedApk;
private ComboboxWithBrowseButton myApkPathCombo;
private JLabel myApkPathLabel;
+ private JRadioButton myUseCompilerManifestFromStructureRadio;
+ private JRadioButton myUseCustomCompilerManifestRadio;
+ private TextFieldWithBrowseButton myCustomCompilerManifestPathField;
public AndroidFacetEditorTab(FacetEditorContext context, AndroidFacetConfiguration androidFacetConfiguration) {
final Project project = context.getProject();
@@ -130,6 +133,9 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
myCustomAptSourceDirField.getButton().addActionListener(new MyFolderFieldListener(myCustomAptSourceDirField,
AndroidAptCompiler.getCustomResourceDirForApt(facet),
false));
+ myCustomCompilerManifestPathField.getButton().addActionListener(new MyFolderFieldListener(myCustomCompilerManifestPathField,
+ AndroidRootUtil.getManifestFileForCompiler(facet),
+ true));
myPlatformChooser.addListener(new AndroidPlatformChooserListener() {
@Override
@@ -176,6 +182,15 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
myUseCustomSourceDirectoryRadio.addActionListener(listener);
myUseAptResDirectoryFromPathRadio.addActionListener(listener);
+ listener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myCustomCompilerManifestPathField.setEnabled(myUseCustomCompilerManifestRadio.isSelected());
+ }
+ };
+ myUseCustomCompilerManifestRadio.addActionListener(listener);
+ myUseCompilerManifestFromStructureRadio.addActionListener(listener);
+
myIsLibraryProjectCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -329,10 +344,17 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
if (myUseCustomSourceDirectoryRadio.isSelected() != myConfiguration.USE_CUSTOM_APK_RESOURCE_FOLDER) {
return true;
}
-
if (checkRelativePath(myConfiguration.CUSTOM_APK_RESOURCE_FOLDER, myCustomAptSourceDirField.getText())) {
return true;
}
+
+ if (myUseCustomCompilerManifestRadio.isSelected() != myConfiguration.USE_CUSTOM_COMPILER_MANIFEST) {
+ return true;
+ }
+ if (checkRelativePath(myConfiguration.CUSTOM_COMPILER_MANIFEST, myCustomCompilerManifestPathField.getText())) {
+ return true;
+ }
+
if (myCopyResourcesFromArtifacts.isSelected() != myConfiguration.COPY_RESOURCES_FROM_ARTIFACTS) {
return true;
}
@@ -495,6 +517,12 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
}
myConfiguration.USE_CUSTOM_APK_RESOURCE_FOLDER = useCustomAptSrc;
+ boolean useCustomCompilerManifest = myUseCustomCompilerManifestRadio.isSelected();
+ if (myConfiguration.USE_CUSTOM_COMPILER_MANIFEST != useCustomCompilerManifest) {
+ runApt = true;
+ }
+ myConfiguration.USE_CUSTOM_COMPILER_MANIFEST = useCustomCompilerManifest;
+
if (myConfiguration.REGENERATE_R_JAVA != myGenerateRJavaWhenChanged.isSelected()) {
runApt = true;
}
@@ -526,6 +554,25 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
myConfiguration.CUSTOM_APK_RESOURCE_FOLDER = relPath != null ? '/' + relPath : "";
}
+ String absCompilerManifestPath = myCustomCompilerManifestPathField.getText().trim();
+ if (useCustomCompilerManifest) {
+ if (absCompilerManifestPath.length() == 0) {
+ throw new ConfigurationException("AndroidManifest.xml path not specified in \"Compiler\" section");
+ }
+ String newCustomCompilerManifestPath = '/' + getAndCheckRelativePath(absCompilerManifestPath, false);
+ if (!SdkConstants.FN_ANDROID_MANIFEST_XML.equals(AndroidUtils.getSimpleNameByRelativePath(newCustomCompilerManifestPath))) {
+ throw new ConfigurationException("Manifest file must have name AndroidManifest.xml");
+ }
+ if (!newCustomCompilerManifestPath.equals(myConfiguration.CUSTOM_COMPILER_MANIFEST)) {
+ runApt = true;
+ }
+ myConfiguration.CUSTOM_COMPILER_MANIFEST = newCustomCompilerManifestPath;
+ }
+ else {
+ String relPath = toRelativePath(absCompilerManifestPath);
+ myConfiguration.CUSTOM_COMPILER_MANIFEST = relPath != null ? '/' + relPath : "";
+ }
+
final AndroidPlatform platform = myPlatformChooser.getSelectedPlatform();
myConfiguration.setAndroidPlatform(platform);
final AndroidFacet facet = myConfiguration.getFacet();
@@ -657,6 +704,14 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
myCustomAptSourceDirField.setText(aptSourceAbsPath != null ? aptSourceAbsPath : "");
myCustomAptSourceDirField.setEnabled(configuration.USE_CUSTOM_APK_RESOURCE_FOLDER);
+ myUseCustomCompilerManifestRadio.setSelected(configuration.USE_CUSTOM_COMPILER_MANIFEST);
+ myUseCompilerManifestFromStructureRadio.setSelected(!configuration.USE_CUSTOM_COMPILER_MANIFEST);
+
+ String compilerManifestPath = configuration.CUSTOM_COMPILER_MANIFEST;
+ String compilerManifestAbsPath = compilerManifestPath.length() > 0 ? toAbsolutePath(compilerManifestPath) : "";
+ myCustomCompilerManifestPathField.setText(compilerManifestAbsPath != null ? compilerManifestAbsPath : "");
+ myCustomCompilerManifestPathField.setEnabled(configuration.USE_CUSTOM_COMPILER_MANIFEST);
+
String apkPath = configuration.APK_PATH;
String apkAbsPath = apkPath.length() > 0 ? toAbsolutePath(apkPath) : "";
myApkPathCombo.getComboBox().getEditor().setItem(apkAbsPath != null ? apkAbsPath : "");
diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java b/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java
index 62dcd9f1128e..e63fa861d677 100644
--- a/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java
+++ b/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java
@@ -47,13 +47,18 @@ public class AndroidRootUtil {
public static VirtualFile getManifestFile(@NotNull Module module) {
AndroidFacet facet = AndroidFacet.getInstance(module);
return facet == null ? null : getFileByRelativeModulePath(module, facet.getConfiguration().MANIFEST_FILE_RELATIVE_PATH, true);
+ }
- /*VirtualFile[] files = ModuleRootManager.getInstance(module).getContentRoots();
- for (VirtualFile contentRoot : files) {
- VirtualFile manifest = contentRoot.findChild(SdkConstants.FN_ANDROID_MANIFEST_XML);
- if (manifest != null) return manifest;
- }
- return null;*/
+ @Nullable
+ public static VirtualFile getCustomManifestFileForCompiler(@NotNull AndroidFacet facet) {
+ return getFileByRelativeModulePath(facet.getModule(), facet.getConfiguration().CUSTOM_COMPILER_MANIFEST, false);
+ }
+
+ @Nullable
+ public static VirtualFile getManifestFileForCompiler(AndroidFacet facet) {
+ return facet.getConfiguration().USE_CUSTOM_COMPILER_MANIFEST
+ ? getCustomManifestFileForCompiler(facet)
+ : getManifestFile(facet.getModule());
}
@Nullable