blob: 23dc53ed3d2f57ec8872d102771b17b17a126680 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.cordova.platforms.android;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import org.netbeans.api.options.OptionsDisplayer;
import org.netbeans.api.progress.ProgressUtils;
import org.netbeans.api.project.Project;
import org.netbeans.modules.cordova.platforms.spi.BuildPerformer;
import org.netbeans.modules.cordova.platforms.spi.Device;
import org.netbeans.modules.web.browser.api.WebBrowser;
import org.netbeans.modules.web.browser.spi.ProjectBrowserProvider;
import org.netbeans.spi.project.ActionProvider;
import static org.netbeans.spi.project.ActionProvider.COMMAND_BUILD;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
/**
*
* @author Jan Becicka
*/
@NbBundle.Messages({
"ERR_Title=Error",
"LBL_CheckingDevice=Connecting to android device...",
"ERR_WebDebug=Cannot connect to Chrome.\nMake sure, that:\n"
+ "\u2022 Device is attached\n"
+ "\u2022 USB Debugging is enabled on your device\n"
+ "\u2022 Your computer and Android device are connected to the same WiFi network",
"ERR_NO_Cordova=NetBeans cannot find cordova or git on your PATH. Please install cordova and git.\n" +
"NetBeans might require restart for changes to take effect.\n"
})
/**
* Cordova Action Provider. Invokes cordova build.
* @author Jan Becicka
*/
public class AndroidActionProvider implements ActionProvider {
private final Project p;
private static final Logger LOGGER = Logger.getLogger(AndroidActionProvider.class.getName());
public AndroidActionProvider(Project p) {
this.p = p;
}
@Override
public String[] getSupportedActions() {
return new String[]{
COMMAND_BUILD,
COMMAND_CLEAN,
COMMAND_RUN,
COMMAND_RUN_SINGLE,
COMMAND_REBUILD
};
}
@NbBundle.Messages({
"LBL_AvdManager=AVD Manager",
"ERR_NO_JDK=NetBeans is currently running on JRE. Cordova Android build requires JDK. Please run NetBeans on JDK to continue."
})
@Override
public void invokeAction(String command, final Lookup context) throws IllegalArgumentException {
final BuildPerformer build = Lookup.getDefault().lookup(BuildPerformer.class);
String checkAndroid = checkAndroid();
if (checkAndroid != null) {
NotifyDescriptor not = new NotifyDescriptor(
checkAndroid,
Bundle.ERR_Title(),
NotifyDescriptor.OK_CANCEL_OPTION,
NotifyDescriptor.ERROR_MESSAGE,
null,
null);
Object value = DialogDisplayer.getDefault().notify(not);
if (NotifyDescriptor.CANCEL_OPTION != value) {
OptionsDisplayer.getDefault().open("Html5/MobilePlatforms"); // NOI18N
}
return;
}
// Quick fix for issue when IDE is running on JRE, Android build fails because it needs javac
String jdkHome = System.getProperty("jdk.home"); //NOI18N
NotifyDescriptor.Message notJDK = new DialogDescriptor.Message(
Bundle.ERR_NO_JDK(),
DialogDescriptor.ERROR_MESSAGE);
if (jdkHome == null || jdkHome.isEmpty()) {
DialogDisplayer.getDefault().notify(notJDK);
return;
} else {
FileObject jdkHomeFO = FileUtil.toFileObject(new File(jdkHome, "bin")); //NOI18N
String javacFileName = Utilities.isWindows() ? "javac.exe" : "javac"; //NOI18N
FileObject javacFO = jdkHomeFO.getFileObject(javacFileName);
if (javacFO == null) {
DialogDisplayer.getDefault().notify(notJDK);
return;
}
}
if (COMMAND_BUILD.equals(command) || COMMAND_CLEAN.equals(command) || COMMAND_REBUILD.equals(command)) {
try {
switch (command) {
case COMMAND_BUILD:
build.perform(BuildPerformer.BUILD_ANDROID, p);
break;
case COMMAND_CLEAN:
build.perform(BuildPerformer.CLEAN_ANDROID, p);
break;
case COMMAND_REBUILD:
build.perform(BuildPerformer.REBUILD_ANDROID, p);
break;
}
} catch (UnsupportedOperationException ex) {
NotifyDescriptor.Message not = new DialogDescriptor.Message(
Bundle.ERR_NO_Cordova(),
DialogDescriptor.ERROR_MESSAGE);
Object value = DialogDisplayer.getDefault().notify(not);
return;
}
} else if (COMMAND_RUN.equals(command) || COMMAND_RUN_SINGLE.equals(command)) {
ProgressUtils.runOffEventDispatchThread(new Runnable() {
@Override
public void run() {
String checkDevices = checkDevices(p);
while (checkDevices != null) {
NotifyDescriptor not = new NotifyDescriptor(
checkDevices,
Bundle.ERR_Title(),
NotifyDescriptor.DEFAULT_OPTION,
NotifyDescriptor.ERROR_MESSAGE,
checkDevices.equals(Bundle.ERR_RunAndroidEmulator())
? new Object[]{
DialogDescriptor.OK_OPTION,
DialogDescriptor.CANCEL_OPTION,
Bundle.LBL_AvdManager()
} : null,
null);
Object value = DialogDisplayer.getDefault().notify(not);
if (NotifyDescriptor.CANCEL_OPTION == value || checkDevices.equals(Bundle.ERR_AdbNotFound())) {
return;
} else if (Bundle.LBL_AvdManager().equals(value)) {
RequestProcessor.getDefault().post(new Runnable() {
@Override
public void run() {
AndroidPlatform.getDefault().manageDevices();
}
});
return;
} else {
checkDevices = checkDevices(p);
}
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
build.perform(BuildPerformer.RUN_ANDROID, p);
} catch (UnsupportedOperationException ex) {
NotifyDescriptor not = new NotifyDescriptor(
Bundle.ERR_NO_Cordova(),
Bundle.ERR_Title(),
NotifyDescriptor.OK_CANCEL_OPTION,
NotifyDescriptor.ERROR_MESSAGE,
null,
null);
Object value = DialogDisplayer.getDefault().notify(not);
if (NotifyDescriptor.CANCEL_OPTION != value) {
OptionsDisplayer.getDefault().open("Html5/MobilePlatforms"); // NOI18N
}
return;
} catch (IllegalStateException ex) {
StatusDisplayer.getDefault().setStatusText(ex.getMessage());
}
}
});
}
}, Bundle.LBL_CheckingDevice(), new AtomicBoolean(), false);
}
}
@Override
public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
return true;
}
@NbBundle.Messages({
"ERR_ConnectAndroidDevice=Please connect Android device and make sure that:\n"
+ "\u2022 USB Debugging is enabled on your device\n"
+ "\u2022 Your computer and Android device are connected to the same WiFi network",
"ERR_RunAndroidEmulator=Please run Android Emulator.",
"ERR_Unknown=Unknown Error.",
"ERR_AdbNotFound=ADB not found. Please make sure that:\n"
+ "\u2022 Android SDK has been installed correctly,\n"
+ "\u2022 Close Android SDK Manager, if it's opened."
})
static String checkDevices(Project p) {
if (!AndroidPlatform.getDefault().adbCommandExists()) {
return Bundle.ERR_AdbNotFound();
}
ProjectBrowserProvider provider = p.getLookup().lookup(ProjectBrowserProvider.class);
WebBrowser activeConfiguration = provider.getActiveBrowser();
try {
if (activeConfiguration.getId().endsWith("_1")) { //NOI18N
for (Device dev : AndroidPlatform.getDefault().getConnectedDevices()) {
if (!dev.isEmulator()) {
return null;
}
}
return Bundle.ERR_ConnectAndroidDevice();
} else {
for (Device dev : AndroidPlatform.getDefault().getConnectedDevices()) {
if (dev.isEmulator()) {
return null;
}
}
return Bundle.ERR_RunAndroidEmulator();
}
} catch (IOException iOException) {
Exceptions.printStackTrace(iOException);
}
return Bundle.ERR_Unknown();
}
@NbBundle.Messages("ERR_AndroidNotConfigured=Android Platform is not configured.\nConfigure?")
static String checkAndroid() {
if (!AndroidPlatform.getDefault().isReady()) {
return Bundle.ERR_AndroidNotConfigured();
}
return null;
}
}