Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Firebase init fails on android device #39

Closed
lowe0292 opened this issue May 30, 2016 · 10 comments
Closed

Firebase init fails on android device #39

lowe0292 opened this issue May 30, 2016 · 10 comments

Comments

@lowe0292
Copy link

lowe0292 commented May 30, 2016

I got the demo to work, but when adding this plugin to angular2-seed-advanced I keep getting this error:

JS: Error in firebase.init: TypeError: Cannot read property 'firebase' of undefined
JS: firebase.init error: TypeError: Cannot read property 'firebase' of undefined

Here's my code:

// libs
import {Store} from '@ngrx/store';
// app
import {FormComponent} from '../../frameworks/core.framework/index';
import {NameListService} from '../../frameworks/app.framework/index';
var firebase = require('nativescript-plugin-firebase');
@FormComponent({
  selector: 'sd-home',
  templateUrl: './app/components/home/home.component.html',
  styleUrls: ['./app/components/home/home.component.css']
})
export class HomeComponent {
  public newName: string = '';
  public count: number = 0;
  constructor(private store: Store<any>, public nameListService: NameListService) {
    firebase.init({
      url: 'https://ng2-test-107d1.firebaseio.com/',
      persist: true
    }).then((instance: any) => {
      firebase.query((result: any) => {
        this.count = result.value;
      }, 'nativescript', { singleEvent: true });
    }, function (error: any) {
      console.log("firebase.init error: " + error);
    });
  }
  /*
   * @param newname  any text as input.
   * @returns return false to prevent default form submit behavior to refresh the page.
   */
  addName(): boolean {
    this.nameListService.add(this.newName);
    this.newName = '';
    return false;
  }
  addOne(): void {
    firebase.setValue('/nativescript', this.count++);
  }
}

What am I missing?

@lowe0292 lowe0292 changed the title Firebase init fails on android Firebase init fails on android device May 31, 2016
@lowe0292
Copy link
Author

Note, I have it working on the iOS emulator, still no luck with my android device (HTC One m8, getting the error above) or the genymotion emulator:

java.lang.RuntimeException: Unable to create application com.tns.NativeScriptApplication: com.tns.NativeScriptException: Failed to find module: "nativescript-plugin-firebase", relative to: /app/tns_modules/
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4710)
    at android.app.ActivityThread.-wrap1(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: com.tns.NativeScriptException: Failed to find module: "nativescript-plugin-firebase", relative to: /app/tns_modules/
    at com.tns.Module.resolvePathHelper(Module.java:220)
    at com.tns.Module.resolvePath(Module.java:60)
    at com.tns.R

Here's the full codebase: https://github.com/castle-dev/ng2-seed-test

@isaackwan
Copy link

isaackwan commented May 31, 2016

I too have encountered this problem. Here is how I solved it:

  1. Installpackages Google Play Services and Google Repository in your Android SDK Manager
  2. Set the applicationId directive in build.gradle

Hope my 2 cents helped!

@nikolal
Copy link

nikolal commented May 31, 2016

@isaackwan Tnank you, this worked for me.

@lowe0292
Copy link
Author

Solved for me too, thanks @isaackwan!

@EddyVerbruggen want me to submit a PR to add this info to the Android Installation section in the README?

@EddyVerbruggen
Copy link
Owner

Thanks guys! I added that applicationId to my own app/App_Resources/Android/app.gradle file but forgot to add it to the readme.

@lowe0292 I'm adding it to the readme after a few tests, thanks for offering!

@zakdances
Copy link

I still don't see it in the readme. Are we suppose to be creating app/App_Resources/Android/app.gradle ourself?

@dagenius007
Copy link

Pls I still get this error
java.lang.RuntimeException: Unable to create application com.tns.NativeScriptApplication: com.tns.NativeScriptException: Failed to find module: "nativescript-plugin-firebase", relative to: /app/tns_modules/
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4710)
at android.app.ActivityThread.-wrap1(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: com.tns.NativeScriptException: Failed to find module: "nativescript-plugin-firebase", relative to: /app/tns_modules/
at com.tns.Module.resolvePathHelper(Module.java:220)
at com.tns.Module.resolvePath(Module.java:60)
at com.tns.R

@Dashue
Copy link

Dashue commented Sep 11, 2017

Looks like you need to install/reinstall nativescript-plugin-firebase?

@dagenius007
Copy link

Still getting same error
App.gradle ;
// Add your native dependencies here:

// Uncomment to add recyclerview-v7 dependency
//dependencies {
// compile 'com.android.support:recyclerview-v7:+'
//}

dependencies {
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
details.useVersion '25.3.1'
}
}
}
}
android {
defaultConfig {
generatedDensities = []
applicationId = "org.nativescript.Mech"

//override supported platforms
// ndk {
//       abiFilters.clear()
//   		abiFilters "armeabi-v7a"
	// }

}
aaptOptions {
additionalParameters "--no-version-vectors"
}
}

Build.gradle;
/*

  • Script builds apk in release or debug mode

  • To run:

  •   	gradle buildapk -Prelease (release mode)
    
  •   	gradle buildapk (debug mode -> default)
    
  • Options:

  •   	-Prelease  //this flag will run build in release mode
    
  •   	-PksPath=[path_to_keystore_file]
    
  •   	-PksPassword=[password_for_keystore_file]
    
  •   	-Palias=[alias_to_use_from_keystore_file]
    
  •   	-Ppassword=[password_for_alias]
    
  •   	-PtargetSdk=[target_sdk]
    
  •   	-PbuildToolsVersion=[build_tools_version]
    
  •   	-PsupportVersion=[support_version]
    
  •   	-PcompileSdk=[compile_sdk_version]
    
  •   	-PdontRunSbg=[true/false]
    

*/

import groovy.json.JsonSlurper //used to parse package.json

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.regex.Pattern;

buildscript {
repositories {
jcenter()
}

dependencies {
	classpath "com.android.tools.build:gradle:2.2.3"
    classpath "com.google.gms:google-services:3.1.0"
	}

}

apply plugin: "com.android.application"

def isWinOs = System.properties['os.name'].toLowerCase().contains('windows')
def metadataParams = new LinkedList ()
def allJarPaths = new LinkedList ()
def configurationsDir = "$projectDir/configurations"
def shouldCreatePluginConfigFile = false
def configStage = "\n:config phase: "
def nodeModulesDir = "../../node_modules/"
def libDir = "$projectDir/../../lib/Android/"
def flavorNames = new ArrayList()
def configDir = file(configurationsDir)

def packageJsonContents = [:]
def excludedDevDependencies = ['/.bin/']

def dontRunSbg = project.hasProperty("dontRunSbg");
def asbgProject = project(":asbg")
asbgProject.ext.outDir = new File("$projectDir", "src/main/java")
asbgProject.ext.jsCodeDir = new File("$projectDir", "src/main/assets/app")

def computeCompileSdkVersion () {
if(project.hasProperty("compileSdk")) {
return compileSdk
}
else {
return 23
}
}

def computeTargetSdkVersion() {
if(project.hasProperty("targetSdk")) {
return targetSdk
}
else {
return 23
}
}

def computeBuildToolsVersion() {
if(project.hasProperty("buildToolsVersion")) {
return buildToolsVersion
}
else {
return "25.0.2"
}
}
project.ext.selectedBuildType = project.hasProperty("release") ? "release" : "debug"

def renameResultApks (variant) {
def name
variant.outputs.each { output ->
def apkDirectory = output.packageApplication.outputFile.parentFile
def abiName = "";
if(output.getFilter(com.android.build.OutputFile.ABI)) {
abiName = "-" + output.getFilter(com.android.build.OutputFile.ABI);
}
def apkNamePrefix = rootProject.name + "-" + variant.buildType.name + abiName
name = apkNamePrefix + ".apk"
output.packageApplication.outputFile = new File(apkDirectory, name);
}
}

// gets the devDependencies declared in the package.json and excludes them from the build
task getDevDependencies {
doLast {
println "$configStage getDevDependencies"

	String content = new File("$projectDir/../../package.json").getText("UTF-8")
	def jsonSlurper = new JsonSlurper()
	def packageJsonMap = jsonSlurper.parseText(content)

	packageJsonContents = packageJsonMap.devDependencies;

	packageJsonContents.each { entry ->
		excludedDevDependencies.add(entry.key + '/platforms/android/**/*.jar')
	}
}

}
////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// CONFIGURATIONS ///////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

android {
compileSdkVersion computeCompileSdkVersion()
buildToolsVersion computeBuildToolsVersion()

defaultConfig {
	minSdkVersion 17
	targetSdkVersion computeTargetSdkVersion()
	ndk {
        abiFilters "armeabi-v7a", "x86"
	}
}

sourceSets.main {
    jniLibs.srcDir "$projectDir/libs/jni"
}

signingConfigs {
    release {
        if(project.hasProperty("release")) {
			if(project.hasProperty("ksPath") &&
				project.hasProperty("ksPassword") &&
				project.hasProperty("alias") &&
				project.hasProperty("password"))
			{
				storeFile file(ksPath)
				storePassword ksPassword
				keyAlias alias
				keyPassword password
			}
		}
    }
}
buildTypes {
    release {
        signingConfig signingConfigs.release
    }
}

applicationVariants.all { variant ->
	renameResultApks(variant)
}

applicationVariants.all { variant ->
	def variantName = variant.name.capitalize()
	def compileSourcesTaskName = "compile${variantName}Sources"
	def compileSourcesTask = project.tasks.findByName(compileSourcesTaskName)

	def generateBuildConfigTask = variant.generateBuildConfig;
	generateBuildConfigTask.finalizedBy(collectAllJars)
	if(!dontRunSbg) {
		collectAllJars.finalizedBy(setProperties)
	}
	
	compileSourcesTask.finalizedBy(buildMetadata)

	// forces packaging of resources and assets AFTER producing metadata
	// Reference: https://github.com/NativeScript/android-runtime/issues/785

	// Ensure metadata has been built and copied in assets before packaging
	variant.outputs.each { output ->
		def abiName = "";
		if (output.getFilter(com.android.build.OutputFile.ABI)) {
			abiName = output.getFilter(com.android.build.OutputFile.ABI)
			def packageTask = project.tasks.findByName("package${output.name}")
			if (packageTask) {
				packageTask.dependsOn(buildMetadata)
			}
		}
	}

	// Compile the Java sources AFTER the Java code-generation step is done
	def compileTask = project.tasks.findByName("compile${variantName}JavaWithJavac")
	if (compileTask) {
		compileTask.dependsOn("asbg:generateBindings")
	}
}

}

repositories {
jcenter()
// used for local *.AAR files
flatDir {
dirs 'libs/aar'
}
}

dependencies {
def supportVer = "22.2.0";
if(project.hasProperty("supportVersion")) {
supportVer = supportVersion
}

compile "com.android.support:support-v4:$supportVer"
compile "com.android.support:appcompat-v7:$supportVer"
debugCompile "com.android.support:design:$supportVer"

// take all jars within the libs dir
compile fileTree(dir: "$projectDir/libs", include: ["**/*.jar"])

// take all jars within the node_modules dir
compile fileTree(dir: nodeModulesDir, include: ["**/platforms/android/**/*.jar"], exclude: excludedDevDependencies)


//when gradle has aar support this will be preferred instead of addAarDependencies
// compile files("$rootDir/libs/aar") {
    // builtBy 'copyAarDependencies'
// }
copyNativeScriptAar()

compile project(':runtime')

}

def copyNativeScriptAar() {
def useV8SymbolsFlag = new File("$projectDir/build-tools/useV8");
def runtimeAarType = "optimized";
if (useV8SymbolsFlag.exists() && !useV8SymbolsFlag.isDirectory()) {
println "Using less-optimized runtime bundle.";
runtimeAarType = "regular";
}

copy {
	from "$projectDir/libs/runtime-libs/nativescript-${runtimeAarType}.aar"
	into "$projectDir/libs/runtime-libs/"
	rename "nativescript-${runtimeAarType}.aar", "nativescript.aar"
}

}

////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// CONFIGURATION PHASE //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

def updateProductFlavorsContent(flavor, dimensionName, oldContent) {
def endIndex = oldContent.length() - 1;
def index = 0;
def newContent = "";
def level = -1;
def dimensionFound = false;

	while(index <= endIndex) {
		if(level == 0 && (oldContent[index] == '"' || oldContent[index] == "'")) {
			def closingQuotes = oldContent.indexOf('"', index + 1);
			if(closingQuotes == -1) {
				closingQuotes = oldContent.indexOf("'", index + 1);
			}

			index = closingQuotes + 1;
			newContent += "\"${flavor}\"";
			continue;
		}

		if(oldContent[index] == "{") {
			level++;	
		}

		if(oldContent[index] == "}") {
			level--;
		}

		if(level > 0) {
			if(!dimensionFound && oldContent.indexOf("dimension", index) == index) {
				newContent += "dimension \"${dimensionName}\"";
				dimensionFound = true;
				index += "dimension ".length();
				def openingQuoutes = oldContent.indexOf('"', index);
				if(openingQuoutes == -1) {
					openingQuoutes = oldContent.indexOf("'", index);
				}

				def closingQuotes = oldContent.indexOf('"', openingQuoutes + 1);
				if(closingQuotes == -1) {
					closingQuotes = oldContent.indexOf("'", openingQuoutes + 1);
				}

				index = closingQuotes + 1;
			}
		}

		newContent += oldContent[index];

		index++;
	}

	return newContent;

}

def createProductFlavorsContent(flavor, dimensionName, includeAndroidContent = true) {
if (includeAndroidContent)
{
def content = """
android {
productFlavors {
"${flavor}" {
dimension "${dimensionName}"
}
}
}
"""
return content;
}
else
{
def content = """
productFlavors {
"${flavor}" {
dimension "${dimensionName}"
}
}
"""
return content;
}
}

def createIncludeFile (filePath, flavor, dimensionName) {
println "\t + creating include.gradle file for ${filePath}"

def defaultIncludeFile = new File(filePath, "include.gradle")
defaultIncludeFile.text =  createProductFlavorsContent(flavor, dimensionName);

}

def sanitizeDimensionName(str) {
return str.replaceAll(/\W/, "")
}

def replaceProductFlavorInContent(content, dimension, flavor) {
def indexStart = content.indexOf("productFlavors");
def index = indexStart + "productFlavors".length();
def indexEnd = -1;
def nestedOpenBraketsCount = 0;

while (index < content.length())
{
	// print content[index];
	if (content[index] == "}")
	{
		nestedOpenBraketsCount--;

		if (nestedOpenBraketsCount == 0)
		{
			indexEnd = index;
			break;
		}
	}
	else if (content[index] == "{")
	{
		nestedOpenBraketsCount++;
	}

	index++;
}

if (indexEnd != -1)
{
	// full content of productFlavors { ... } -> the substring is parenthesis to parenthesis -> { ... }
  def oldProductFlavorsText = content.substring(indexStart, indexEnd + 1);

  def newProductFlavorsContent = updateProductFlavorsContent(flavor, dimension, oldProductFlavorsText);
  
  return content.replace(oldProductFlavorsText, newProductFlavorsContent);
}
else
{
    def androidContentExists = content.indexOf("android {") != -1;
    def newProductFlavorsContent = createProductFlavorsContent(flavor, dimension, !androidContentExists);
    
    if (androidContentExists)
    {
       return content.replace("android {", "android { ${newProductFlavorsContent}");
    }
    else
    {
       return "${newProductFlavorsContent} \t ${content}"
    }
}

}

// make sure the include.gradle file provided by the user has only allowed characters in dimension attribute and remove any invalid characters if necessary
def updateIncludeGradleFile(targetFile, dimensionName, flavor) {
def fileEntry = new File(targetFile.getAbsolutePath());
def content = fileEntry.text;
def replacedContent = replaceProductFlavorInContent(content, dimensionName, flavor);
fileEntry.text = replacedContent;
}

def renamePluginDirToFlavorName(directory, flavor) {
def parentName = directory.getName();
def parentFile = new File("src", parentName);
if (parentFile.exists())
{
def targetDirName = new File("src", flavor);
println "Renaming plugin directory to flavor name: ${parentFile.getAbsolutePath()} -> ${targetDirName.getAbsolutePath()}";
parentFile.renameTo(targetDirName);
}
}

def flavorNumber = 0

task createDefaultIncludeFiles {
description "creates default include.gradle files for added plugins IF NECESSARY"
println "$configStage createDefaultIncludeFiles"
def ft = file(configurationsDir)

ft.listFiles().each { file ->
	if (file.isDirectory()) {
		shouldCreatePluginConfigFile = true
		def hasChildrenDirs = false
		file.listFiles().each { subFile ->
			if (subFile.isDirectory()) {
				hasChildrenDirs = true
			}
		}

		// if plugin is scoped - traverse its children directories
		// e.g. @scope/plugin-with-android-aars 
		if (hasChildrenDirs) {
			file.listFiles().each { subFile ->
				if (subFile.isDirectory()) {
					createIncludeGradleForPlugin(subFile, flavorNumber++, flavorNames)
				}
			}
		} else {
			createIncludeGradleForPlugin(file, flavorNumber++, flavorNames)
		}			
	}
}

}

def createIncludeGradleForPlugin(file, flavorNumber, flavorNames) {
def parentDir = new File(file.getParent())
def parentName = parentDir.name
def dirToRename = file

if (parentName.indexOf("@") == 0) {
	dirToRename = new File(parentName + "_" + file.name)
}

def foundIncludeFile = false
def fileName = file.name
def dimensionName = sanitizeDimensionName(fileName)

def flavor = "F" + flavorNumber
println "\t+found plugins: " + fileName
file.listFiles().each { subFile ->
	if (subFile.name == "include.gradle") {
		foundIncludeFile = true
		updateIncludeGradleFile(subFile, dimensionName, flavor)
							renamePluginDirToFlavorName(dirToRename, flavor);
	}
}

flavorNames.add('"' + dimensionName + '"')

if (!foundIncludeFile) {
	createIncludeFile(file.getAbsolutePath() , flavor, dimensionName)
	renamePluginDirToFlavorName(dirToRename, flavor);
}

}

task createPluginsConfigFile {
description "creates product flavor config file based on what plugins are added"

if (configDir.exists()) {
	println "$configStage createPluginsConfigFile"
	
	def flavorsFile = new File("$configurationsDir/include.gradle")

	if(shouldCreatePluginConfigFile) {
		println "\t Creating product flavors include.gradle file in $configurationsDir folder..."
		def flavors = flavorNames.join(", ")
		
		def content = """

android {
flavorDimensions ${flavors}
}
"""

		flavorsFile.text =  content
	}
}

}

task pluginExtend {
description "applies additional configuration"

def pathToAppGradle = "$projectDir/../../app/App_Resources/Android/app.gradle" 
def appGradle = file(pathToAppGradle)
if(appGradle.exists()) {
	apply from: pathToAppGradle
}

if(configDir.exists()) {
println "$configStage pluginExtend"
	configDir.eachFileRecurse(groovy.io.FileType.FILES) {
		if(it.name.equals('include.gradle')) {
			println "\t+applying configuration from: " + it
			apply from: it
		}
	}
}

}

//// doesn't work unless task is explicitly called (TODO: research configurations hook)
// addAarDependencies.dependsOn(copyAarDependencies)
// createDefaultIncludeFiles.dependsOn(addAarDependencies)
// createPluginsConfigFile.dependsOn(createDefaultIncludeFiles)
// pluginExtend.dependsOn(createPluginsConfigFile)

////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// BEFORE EXECUTION /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

// we need to copy all dependencies into a flat dir, as pointed by the repositories configurations at the top
task copyAarDependencies (type: Copy) {
def filterAarFilesFn = { path, attrs ->
String pathString = path.toString();
def isBin = Pattern.matches("./\.bin/.", pathString);
def isAar = Pattern.matches(".*\.aar$", pathString);
return !isBin && isAar;
}

def mapToStringFn = { path ->
	return path.toString();
}

Object[] files = Files.find(
			Paths.get("$projectDir", "$nodeModulesDir"),
			Integer.MAX_VALUE,
			filterAarFilesFn,
			java.nio.file.FileVisitOption.FOLLOW_LINKS
		)
		.map(mapToStringFn)
		.toArray();

into "$projectDir/libs/aar"
from files

}

task addAarDependencies {
doLast {
println "$configStage addAarDependencies"
// manually traverse all the locally copied AAR files and add them to the project compilation dependencies list
FileTree tree = fileTree(dir: "$projectDir/libs/aar", include: ["**/*.aar"])
tree.each { File file ->
// remove the extension of the file (.aar)
def length = file.name.length() - 4
def fileName = file.name[0..<length]
println "\t+adding dependency: " + file.getAbsolutePath()
project.dependencies.add("compile", [name: fileName, ext: "aar"])
}
}
}

////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// EXECUTUION PHASE /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

task cleanLocalAarFiles(type: Delete) {
delete fileTree(dir: "$projectDir/libs/aar", include: ["*.aar"])
}

task ensureMetadataOutDir {
def outputDir = file("$projectDir/metadata/output/assets/metadata")
outputDir.mkdirs()
}

task collectAllJars {
description "gathers all paths to jar dependencies before building metadata with them"

def explodedAarDir = project.buildDir.getAbsolutePath() + "/intermediates/exploded-aar/"
def sdkPath = android.sdkDirectory.getAbsolutePath();
def androidJar = sdkPath + "/platforms/" + android.compileSdkVersion + "/android.jar"

doFirst {
	configurations.compile.each { File dependencyFile ->
		logger.info("Task: collectAllJars: dependency file: " + dependencyFile.getAbsolutePath())
		allJarPaths.add(dependencyFile.getAbsolutePath())
	}
	
	allJarPaths.add(androidJar);
	
	def ft = fileTree(dir: explodedAarDir, include: "**/*.jar")
	ft.each { currentJarFile ->
		allJarPaths.add(currentJarFile.getAbsolutePath())
	}

	metadataParams.add("metadata-generator.jar");
	metadataParams.add("$projectDir/metadata/output/assets/metadata");
	def jars = new LinkedList<File>()
	for(def i = 0; i < allJarPaths.size(); i++) {
		metadataParams.add(allJarPaths.get(i));
		def f = new File(allJarPaths.get(i))
		if (f.getName().endsWith(".jar")) {
			jars.add(f)
		}
	}
	
	asbgProject.ext.jarFiles = jars
}

}

task buildMetadata (type: JavaExec) {
description "builds metadata with provided jar dependencies"

inputs.files(allJarPaths)
inputs.dir("$buildDir/intermediates/classes")

outputs.files("metadata/output/assets/metadata/treeNodeStream.dat", "metadata/output/assets/metadata/treeStringsStream.dat", "metadata/output/assets/metadata/treeValueStream.dat")

doFirst {
	// get compiled classes to pass to metadata generator		
	// these need to be called after the classes have compiled		
	def classesDir = "$buildDir/intermediates/classes"		

	def classesSubDirs = new File(classesDir).listFiles()
	def selectedBuildType = project.ext.selectedBuildType

	for (File subDir: classesSubDirs) {
		if (!subDir.getName().equals(selectedBuildType)) {
			def subDirBuildType = new File(subDir, selectedBuildType)
			if (subDirBuildType.exists()) {
				metadataParams.add(subDirBuildType.getAbsolutePath());
			}
		}
	}

	def classesDirBuildType = new File(classesDir, selectedBuildType)
	if (classesDirBuildType.exists()) {
		metadataParams.add(classesDirBuildType.getAbsolutePath())
	}

	workingDir "build-tools"
	main "-jar"

	logger.info("Task buildMetadata: Call metadata-generator.jar with arguments: " + metadataParams.toString().replaceAll(',', ''))
	args metadataParams.toArray()
}

doLast {
	copy {
		from "$projectDir/metadata/output/assets/metadata"
		into "$projectDir/src/main/assets/metadata"
	}
}

}

task generateTypescriptDefinitions (type: JavaExec) {
def paramz = new ArrayList();
def includeDirs = ["com.android.support", "/platforms/" + android.compileSdkVersion]

doFirst {
	delete "build-tools/typings"

	workingDir "build-tools"

	main "-jar"

	paramz.add("dts-generator.jar");
	paramz.add("-input");

	for (String jarPath: project.jarFiles) {
		// don't generate typings for runtime jars and classes
		if (shouldIncludeDirForTypings(jarPath, includeDirs)) {
			paramz.add(jarPath);
		}
	}

	paramz.add("-output");
	paramz.add("typings");

	logger.info("Task generateTypescriptDefinitions: Call dts-generator.jar with arguments: " + paramz.toString().replaceAll(',', ''))
	args paramz.toArray();
}

}

generateTypescriptDefinitions.onlyIf {
project.hasProperty("generateTypings") && Boolean.parseBoolean(project.generateTypings)
}

def shouldIncludeDirForTypings(path, includeDirs) {
for (String p: includeDirs) {
if (path.indexOf(p) > -1) {
return true;
}
}

return false;

}

task copyTypings {
doLast {
println "Copied generated typings to application root level. Make sure to import android.d.ts in reference.d.ts"

	copy {
		from "$projectDir/build-tools/typings"
		into "$projectDir/../../"
	}
}

}

copyTypings.onlyIf({
generateTypescriptDefinitions.didWork;
})

task validateAppIdMatch {
doLast {
def packageJsonFile = new File("$projectDir/../../package.json");
def lineSeparator = System.getProperty("line.separator");

	if (packageJsonFile.exists() && !project.hasProperty("release")) {
		String content = packageJsonFile.getText("UTF-8")
		def jsonSlurper = new JsonSlurper()
		def packageJsonMap = jsonSlurper.parseText(content)

		if (packageJsonMap.nativescript.id != android.defaultConfig.applicationId) {
			def errorMessage = "${lineSeparator}WARNING: The Application identifier is different from the one inside 'package.json' file.$lineSeparator" +
				"NativeScript CLI might not work properly.$lineSeparator" +
				"Update the application identifier in package.json and app.gradle so that they match.";
			logger.error(errorMessage);
		}
	}
}

}

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// OPTIONAL TASKS //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
task setProperties {
project.ext.jarFiles = []
doLast {
def list = [];
allJarPaths.each({f ->
if(f.endsWith(".jar")) {
list.add(f);
}
})
project.jarFiles = list;
}
}

setProperties.finalizedBy("asbg:generateBindings", generateTypescriptDefinitions)

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// EXECUTION ORDER /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

// -- configuration phase
// 1. Copy *.aar dependencies
// 2. Add *.aar dependencies
// 3. create default include files
// 4. create plugins config file
// 5. plugin extend (apply from include files)

// --execution phase

ensureMetadataOutDir.dependsOn(cleanLocalAarFiles)
collectAllJars.dependsOn(ensureMetadataOutDir)
buildMetadata.dependsOn(collectAllJars)
generateTypescriptDefinitions.finalizedBy(copyTypings)

//DO NOT UNCOMMENT
// mergeAssets.dependsOn(copyMetadata) -> look in CONFIGURATIONS(top) in android.applicationVariants to see how it's done

task buildapk {
// problem is compile dependencies need to be changed before configuration stage
// and this is the only way so far
tasks.copyAarDependencies.execute()
tasks.addAarDependencies.execute()

//done to build only necessary apk
if(project.hasProperty("release")) {
	dependsOn "assembleRelease"
}
else {
	dependsOn "assembleDebug"
}

}

//////// custom clean ///////////
task deleteMetadata (type: Delete){
delete "$projectDir/metadata/output"
}

task deleteFlavors (type: Delete){
doLast {
def srcDir = new File("$projectDir/src")
srcDir.listFiles().each({ f ->
if(!f.getName().equals("main") &&
!f.getName().equals("debug") &&
!f.getName().equals("release")) {
delete f
}
})
}
}

task deleteConfigurations (type: Delete) {
delete "$projectDir/configurations"
}

task deleteGeneratedBindings(type: Delete) {
delete "$projectDir/src/main/java/com/tns/gen"
}

buildapk.finalizedBy("validateAppIdMatch");
deleteMetadata.dependsOn(":asbg:clean")
deleteFlavors.dependsOn(deleteMetadata)
deleteConfigurations.dependsOn(deleteFlavors)
deleteGeneratedBindings.dependsOn(deleteConfigurations)
clean.dependsOn(deleteGeneratedBindings)

@dagenius007
Copy link

I would really appreciate if someone can help me out.This is my first application

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants