Module missing in Android Studio and Gradle sync fails - android-studio

I have set up a brand new project in Android Studio 1.1 RC 1:
Created an Android project [app] (because there is no way to create an App Engine backend project right away).
Added an existing backend module by first creating a new App Engine module and then manually importing the files [backend].
Removed the Android app module [app].
Added a Java library module, same procedure, first creating a new module, then importing files [common].
Everything compiles fine, but Android Studio has two problems:
When I look at Project Structure, the [common] module is missing in the left pane, but it still appears as referenced module in the right pane!?
My Project tree looks fine and all modules are recognized, but gradle is telling me the sync failed.
Gradle says "Task '' not found in root project" ('' is empty string as it seems). I get a Warning and an exception in the log when running from Terminal, but it doesn't seem to be related (related to Indexing), so I haven't included it here.
settings.gradle has both modules specified:
include ':backend', ':common'
I tried to exchange the .iml file of the main project with a fake one which contains both modules, with the result that (besides multiple side effects) both modules were there. (I restored the original state because of the side-effects.)
Here are my gradle files:
Root module:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.1'
}
}
allprojects {
repositories {
jcenter()
}
}
[backend]
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.google.appengine:gradle-appengine-plugin:1.9.17'
}
}
repositories {
jcenter();
}
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'appengine'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
dependencies {
appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.17'
compile 'com.google.appengine:appengine-endpoints:1.9.17'
compile 'com.google.appengine:appengine-endpoints-deps:1.9.17'
compile 'javax.servlet:servlet-api:2.5'
compile 'com.googlecode.objectify:objectify:5.1.3'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'io.jsonwebtoken:jjwt:0.4'
compile project(':common')
}
appengine {
downloadSdk = true
appcfg {
oauth2 = true
}
endpoints {
getClientLibsOnBuild = true
getDiscoveryDocsOnBuild = true
}
}
[common]
apply plugin: 'java'
task sourcesJar(type: Jar, dependsOn:classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives sourcesJar
}
dependencies {
compile 'com.google.http-client:google-http-client-android:1.18.0-rc'
compile 'com.google.code.gson:gson:2.3.1'
}
apply plugin: 'maven'
group = 'cc.closeup'
version = 'v2-2.0-SNAPSHOT'
install {
repositories.mavenInstaller {
pom.artifactId = 'common'
pom.packaging = 'jar'
}
}
Any ideas? Anything else that you'd like to see here?

If you want to build an AE project only. You could try this tutorial for intellij idea jetbrains.com/idea/help/creating-google-app-engine-project.html

My mistake was I removed [app]. It seems that if you create an App Engine backend module, you must keep a "fake" frontend module in the same project to keep Android Studio/gradle happy.
In earlier Android Studio versions it was possible to remove the frontend module without problems, but it seems Google has locked this somehow. It still works when I keep the fake frontend module.
--
Why I configured it this way? In my configuration, I have backend and frontend modules in different projects, and I have the backend project install libraries into local Maven, which I then pick up within my frontend project (with a team you would choose a local Maven server). This configuration has multiple advantages, for example that I can test backend/frontend on two screens simultaneously without switching back and forth all the time. Some companies may also want this configuration to keep their backend code separate and secure.

Related

Could not find org.nodejs:x64

When I try to build my Frontend app I get
Could not resolve all dependencies for configuration ':frontend:nodeDist'.
> Could not find org.nodejs:x64/node:6.17.1.
Searched in the following locations:
http://nodejs.org/dist/v6.17.1/ivy.xml
http://nodejs.org/dist/v6.17.1/x64/node.exe
On another machine it downloads the node without issue from http://nodejs.org/dist/v6.17.1/win-x64/node.exe
Why does my machine not create the same download url with win-x64 instead of x64?
my build.gradle contains:
buildscript {
dependencies {
classpath 'com.moowork.gradle:gradle-node-plugin:0.10'
}
}
apply plugin: 'com.moowork.node'
node {
version = '6.17.1'
npmVersion = '2.10.1'
download = true
}
upgrading the versions is not an option in my case

Building NodeJS using Gradle

I'm very new to Gradle. I started reading about it yesterday. I found an example build.gradle that builds a node application. I'm a little bit confused in the contents of the file. I'm not sure which ones are reserved or predefined words. One of the strings is node. It wasn't used somewhere but I figured out it was needed by the node plugin.
buildscript {
repositories {
mavenCentral()
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'com.moowork.gradle:gradle-node-plugin:1.2.0'
}
}
apply plugin: 'base'
apply plugin: 'com.moowork.node' // gradle-node-plugin
node {
/* gradle-node-plugin configuration
https://github.com/srs/gradle-node-plugin/blob/master/docs/node.md
Task name pattern:
./gradlew npm_<command> Executes an NPM command.
*/
// Version of node to use.
version = '10.14.1'
// Version of npm to use.
npmVersion = '6.4.1'
// If true, it will download node using above parameters.
// If false, it will try to use globally installed node.
download = true
}
npm_run_build {
// make sure the build task is executed only when appropriate files change
inputs.files fileTree('public')
inputs.files fileTree('src')
// 'node_modules' appeared not reliable for dependency change detection (the task was rerun without changes)
// though 'package.json' and 'package-lock.json' should be enough anyway
inputs.file 'package.json'
inputs.file 'package-lock.json'
outputs.dir 'build'
}
// pack output of the build into JAR file
task packageNpmApp(type: Zip) {
dependsOn npm_run_build
baseName 'npm-app'
extension 'jar'
destinationDir file("${projectDir}/build_packageNpmApp")
from('build') {
// optional path under which output will be visible in Java classpath, e.g. static resources path
into 'static'
}
}
// declare a dedicated scope for publishing the packaged JAR
configurations {
npmResources
}
configurations.default.extendsFrom(configurations.npmResources)
// expose the artifact created by the packaging task
artifacts {
npmResources(packageNpmApp.archivePath) {
builtBy packageNpmApp
type 'jar'
}
}
assemble.dependsOn packageNpmApp
String testsExecutedMarkerName = "${projectDir}/.tests.executed"
task test(type: NpmTask) {
dependsOn assemble
// force Jest test runner to execute tests once and finish the process instead of starting watch mode
environment CI: 'true'
args = ['run', 'test']
inputs.files fileTree('src')
inputs.file 'package.json'
inputs.file 'package-lock.json'
// allows easy triggering re-tests
doLast {
new File(testsExecutedMarkerName).text = 'delete this file to force re-execution JavaScript tests'
}
outputs.file testsExecutedMarkerName
}
check.dependsOn test
clean {
delete packageNpmApp.archivePath
delete testsExecutedMarkerName
}
Also, how is the build.gradle parsed? I'm also wondering how it is able to magically download node and npm tools.
This is a very general synopsis:
Gradle aims to hide away the logic from developers.
Most *.gradle files contain configuration blocks (closures) to specify HOW logic should run.
Plugins augment gradle with more configurable logic.
Also, 'convention over configuration' is a practice emphasize in gradle and its plugins, providing sensible defaults to minimize developers' configuration efforts.
The com.moowork.node plugin is configured through the node extension block.
Extension blocks are gradle's way to allow plugins to add more 'reserved' words to the standard gradle model.
The download = true configuration tells the plugin to download node (version = '10.14.1') and nmp (npmVersion = '6.4.1') in your project's root (unless you override its defaults as well).
The download of these tools will occur when any of the plugin's task is invoked.
Hope this helps.
In your snippet only true is keyword, the other things are methods or getters coming from Gradle or Node JS plugin:
apply plugin: ... is a method from org.gradle.api.Project.apply(java.util.Map<String, ?>)
node is a method autogenerated by Gradle with signature void node(Closure<com.moowork.gradle.node.NodeExtension>) (method accepting a code block), see https://github.com/srs/gradle-node-plugin/blob/master/src/main/groovy/com/moowork/gradle/node/NodeExtension.groovy
node { version = ... } - version, npmVersion are fields from NodeExtension class
other things similarly, everything is a method or a field. If you're using IntelliJ, use Ctrl+mouse click to navigate to the originating method/field declaration.

writing nodejs applications in kotlin with intellij idea ce

I am trying to develop a Nodejs application using Kotlin 1.3.11 using the IntelliJ IDEA CE development environment. Unfortunately I haven't made any progress towards a running application. To ensure everything is setup correctly I want to print out a simple "hello world".
I searched for articles or tutorials about the topic but I didn't find much about bringing those three together (Kotlin, IntelliJ, Nodejs). The most specific ones which I found are:
a medium post and another post.
As far as I (believe to) know, there are three major steps:
calling initializing the node app via npm and using npm to install the node dependencies like kotlin and expressjs
creating a build.gradle to define other dependencies and tasks
creating an IntelliJ IDEA project
I tried to perform the steps in different orders but I never came to a running application. Also I searched in IntelliJ's documentation but the Nodejs integration isn't a feature of the free community edition. There isn't a description how to make Kotlin and Nodejs work together too.
Has anyone here successfully tried to do that (or failed and knows why it is not going to work)? Do I have to use another IDE or to write my own build tools/toolchain?
Sincerely J.
I haven't done this in IDEA CE, but theoretically, this should work.
Prerequisites: You have node installed, you can execute gradle tasks
This is a Minimum Configuration, There is a comprehensive one. Add a comment if intrested for that
Step 1:Create a new Kotlin/JS project (with gradle) and make sure that your gradle build file looks like this
group 'node-example'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.3.11'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin2js'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}
task npmInit(type: Exec) {
commandLine "npm", "init", "-y"
}
task npmInstall(type: Exec) {
commandLine "npm", "install", "kotlin", "express", "--save"
}
task npmRun(type: Exec) {
commandLine "node", "node/index.js"
}
npmRun.dependsOn(build)
Step 2: After syncing your build.gradle in step 1 run the gradle tasks npmInit and npmInstall
./gradlew :npmInit
./graldew :npmInstall
Step 3:
Create your kotlin file (index.kt/main.kt/whatever.kt) in src/main/kotlin and test the code below
external fun require(module:String):dynamic
fun main(args: Array<String>) {
println("Hello JavaScript!")
val express = require("express")
val app = express()
app.get("/", { req, res ->
res.type("text/plain")
res.send("Kotlin/JS is kool")
})
app.listen(3000, {
println("Listening on port 3000")
})
}
Step 4: RTFA - Run The App
Run the gradle task npmRun
./gradlew :npmRun
Hope that helps
Note:
1. This template was pulled from the medium post you asked above and modified a little
2. Remember to run your gradle tasks using sudo (if you are using linux)
Edit: Alternatively, you could clone https://github.com/miquelbeltran/kotlin-node.js and follow the instructions in the read me.
I managed to get the Medium post to work by replacing gradle build with the following (since the post was published in 2017(!) and requires a much older version of Gradle):
Comment out the entire contents of build.gradle like so:
/*group 'node-example'
...
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}*/
Run this command in the command prompt: (3.4.1 was the latest version of Gradle just before the Medium post was published.)
gradle wrapper --gradle-version=3.4.1
Uncomment out build.gradle:
group 'node-example'
...
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}
Run this command in place of gradle build:
gradlew build
And finally run this command as in the post: (As of writing this answer on StackOverflow, Node.js does not be downgraded and the current LTS version 10.16.0 works perfectly.)
node node/index.js

How to detect when dependency library version updates exist in build.gradle in AndroidStudio project

I've an android project with two modules (typical front-end app and backend). I have three build.gradle files, one in each module and one in the root.
The way I've structured my dependencies is by extracting all the versions into separate variables in the root level build.gradle as such
ext {
// SDK and tools
MIN_SDK_VERSION = 19
TARGET_SDK_VERSION = 23
COMPILE_SDK_VERSION = 23
BUILD_TOOLS_VERSION = '24'
// app dependencies
GOOGLE_API_CLIENT_VERSION = '1.19.0'
GOOGLE_PLAY_SERVICES_VERSION = '8.4.0'
ANDROID_SUPPORT_LIB_VERSION = '23.1.0'
[...]
// backend dependencies
[...]
}
which are later used in my say app build.gradle file as such
dependencies {
[...]
compile(group: 'com.google.oauth-client', name: 'google-oauth-client', version: rootProject.ext.GOOGLE_API_CLIENT_VERSION)
/////////////////////////////////
// Google Play Services explicit dependency
compile(group: 'com.google.android.gms', name: 'play-services-auth', version: rootProject.ext.GOOGLE_PLAY_SERVICES_VERSION)
compile(group: 'com.google.android.gms', name: 'play-services-plus', version: rootProject.ext.GOOGLE_PLAY_SERVICES_VERSION)
[...]
/////////////////////////////////
// Local Testing
testCompile(group: 'junit', name: 'junit', version: rootProject.ext.JUNIT_VERSION)
testCompile(group: 'pl.pragmatists', name: 'JUnitParams', version: rootProject.ext.JUNIT_PARAMS_VERSION)
[...]
}
NOTE: I found that idea in a tutorial somewhere and I thought it was very nifty.
However, I'm struggling to keep track of which lib versions are available, what is upgradable, etc. It is becoming hard to keep track of these things as I have a reasonably sized list of dependencies. Curious how others have approached this problem. Thanks.
A summary of how I manage dependencies.
All dependency definitions are defined in gradle/dependencies.gradle, which is applied to all projects and the buildscript. I usually break it into three categories. A full example is here.
ext {
versions = [
caffeine: '2.3.1',
]
test_versions = [
testng: '6.9.12',
]
plugin_versions = [
versions: '0.13.0',
]
libraries = [
caffeine: "com.github.ben-manes.caffeine:caffeine:${versions.caffeine}",
]
test_libraries = [
testng: dependencies.create("org.testng:testng:${test_versions.testng}") {
exclude group: 'junit'
},
]
gradle_plugins = [
versions: "com.github.ben-manes:gradle-versions-plugin:${plugin_versions.versions}",
]
}
Then in my root project I bootstrap it as,
buildscript {
apply from: "${rootDir}/gradle/dependencies.gradle"
repositories {
jcenter()
}
dependencies {
gradle_plugins.each { name, dependency -> classpath dependency }
}
}
allprojects {
apply from: "${rootDir}/gradle/dependencies.gradle"
repositories {
jcenter()
}
}
This allows defining the dependency in a project as,
dependencies {
compile libraries.caffeine
}
To detect newer versions I wrote the gradle-versions-plugin. That generates a report by querying the repositories for the version information and comparing it to your definitions. I run it manually every so often, but others script it in their CI and use the json or xml reports.
There are a few other approaches that were developed after I wrote my plugin. Spring's dependency-management-plugin works with Maven BOMs, as does Netfix's nebula-dependency-recommender-plugin. Netflix uses gradle-dependency-lock-plugin to define dynamic versions and generate a lock file to fix a release. There are also dependency version alerting services, though a simple CI job is likely equivalent.
I've never used any of the alternatives as they seem less intuitive (to me), came out years after I had a nice solution, and it is a familiar approach if you come from Maven. Hopefully someone else can shed light on the benefits of other approaches.

Android Studio upgrade to 0.8.5 leads to Gradle errors

My Gradle was working up until I upgraded to Android Studio 0.8.5. Now the gradle build is broken with the error message:
Error:Relying on packaging to define the extension of the main artifact has been deprecated and is scheduled to be removed in Gradle 2.0
(of class java.lang.String)
I am attaching the build.gradle file for reference:
buildscript {
repositories {
mavenCentral()
maven { url 'http://saturday06.github.io/gradle-android-scala-plugin/repository/snapshot' }
flatDir {
dirs 'libs/'
}
// flatDir {
// dirs '/Users/sto/workspace/robolectric-gradle-plugin.sonny/build/libs/'
// }
// flatDir {
// dirs '/Users/sto/workspace/gradle-android-scala-plugin/build/libs/'
// }
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.+'
classpath 'jp.leafytree.gradle:gradle-android-scala-plugin:1.0-SNAPSHOT'
classpath 'org.robolectric:robolectric-gradle-plugin.sonny:0.12.1'
classpath "commons-io:commons-io:2.4"
classpath 'net.lingala.zip4j:zip4j:1.3.2'
}
}
repositories {
mavenCentral()
flatDir {
dirs 'libs/'
}
}
apply plugin: 'com.android.application'
apply plugin: 'android-scala'
apply plugin: 'robolectric'
robolectric {
include '**/*Test*.class'
}
android {
compileSdkVersion 19
buildToolsVersion '20.0.0'
defaultConfig {
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName '1.0'
// testInstrumentationRunner "android.test.InstrumentationTestRunner"
testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
}
packagingOptions {
exclude 'rootdoc.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'decoder.properties'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
exclude 'LICENSE.txt'
}
sourceSets {
main {
java.srcDirs = ['src/main/gen-java', 'src/main/java', 'src/main/scala']
}
androidTest.setRoot('src/androidTest/')
androidTest {
java.srcDirs = ['src/androidTest/scala', 'src/androidTest/java']
}
}
android {
lintOptions {
abortOnError false
}
}
buildTypes {
debug {
runProguard true
proguardFile file('proguard-rules-debug.txt')
}
release {
runProguard true
proguardFile file('proguard-rules.txt')
}
}
}
dependencies {
compile project(':swiper')
compile 'org.scala-lang:scala-library:2.11.2'
compile 'org.json4s:json4s-native_2.11:3.2.10'
compile 'com.google.android.gms:play-services:4.0.30'
compile 'com.google.android:android:4.1.1.4'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.2'
compile 'com.loopj.android:android-async-http:1.4.4'
compile 'com.edmodo:cropper:1.0.1'
compile 'de.hdodenhof:circleimageview:1.1.1'
compile 'org.fusesource.mqtt-client:mqtt-client:1.10'
compile 'log4j:log4j:1.2.17'
compile 'de.mindpipe.android:android-logging-log4j:1.0.3'
compile('org.apache.thrift:libthrift:0.9.1') {
transitive = false
}
compile 'ch.hsr:geohash:1.0.10'
compile 'org.slf4j:slf4j-android:1.7.7'
androidTestCompile('junit:junit:4.11') {
// exclude module: 'hamcrest-core'
}
androidTestCompile('org.robolectric:robolectric:2.3') {
exclude module: 'classworlds'
exclude module: 'commons-logging'
exclude module: 'httpclient'
exclude module: 'maven-artifact'
exclude module: 'maven-artifact-manager'
exclude module: 'maven-error-diagnostics'
exclude module: 'maven-model'
exclude module: 'maven-project'
exclude module: 'maven-settings'
exclude module: 'plexus-container-default'
exclude module: 'plexus-interpolation'
exclude module: 'plexus-utils'
exclude module: 'wagon-file'
exclude module: 'wagon-http-lightweight'
exclude module: 'wagon-provider-api'
}
}
I am still able to build using gradle (v1.12) from command line, but without using Studio I can't set my usual breakpoints for debug.
Update:
Turns out what was causing this issue for me (and likely for you, given the build file above) was the Scala plugin. There was a bug with the Scala plugin preventing Android Studio from importing Gradle projects. The fix for this has already been pushed live, so to get Android Studio working again you can either disable the Scala plugin or update it.
Open Settings/Preferences
Open the Plugins section on the left
Find the Scala plugin
Right click on the plugin and click Reload List of Plugins
Right click on the plugin again and click Update Plugin
This allowed me to do a Gradle sync and build from Android Studio again, I hope it helps for you!
Original answer below:
It looks like this is a bug with Android Studio. Hopefully it'll be fixed soon.
In the meantime, you can debug your application without launching it from Android Studio by attaching the debugger to a running process of the application. You can do this two ways.
Via the menus: Run -> Attach Debugger to Android Process
Pressing the button that is two to the right of the play/build button. It looks like a grey phone/rectangle with a little green bug in the bottom right
After you do this, a dialog will show up listing available applications to debug. Select your application and press OK. Your breakpoints should now work.
If you need to debug something that happens on app startup, you can tell Android to wait for a debugger when launching certain applications with the following steps:
On the phone open the Android Settings
Open the Developer Options
Make sure Wait for debugger is checked
Press Select debug app and choose your application
Then when you start your application, it'll wait for you to attach a debugger via one of the two methods mentioned above.
Hope this helps!

Resources