Skip to content
This repository was archived by the owner on Nov 17, 2022. It is now read-only.

Commit 00737dc

Browse files
authored
Merge pull request #1598 from NativeScript/trifonov/gradle-hooks
docs(android): add gradle hooks page
2 parents 0eaa608 + 3fe7b0f commit 00737dc

File tree

9 files changed

+127
-66
lines changed

9 files changed

+127
-66
lines changed

docs/core-concepts/android-runtime/advanced-topics/V8-heap-snapshots.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
nav-title: "V8 Heap Snapshot"
33
title: "V8 Heap Snapshot"
44
description: "Using V8 heap snapshots with the Android Runtime"
5-
position: 3
5+
position: 7
66
---
77

88
# Deprecated

docs/core-concepts/android-runtime/advanced-topics/custom-flags.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Custom Flags"
33
description: "Configure various V8 engine flags in order to improve the performance of your app, or to obtain more comprehensive information during debugging"
4-
position: 5
4+
position: 4
55
previous_url: /core-concepts/android-runtime/advanced-topics/v8-flags
66
slug: android-custom-flags
77
---

docs/core-concepts/android-runtime/advanced-topics/debug-android-runtime.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Debugging the Android Runtime within your app's Android Studio project
33
description: Add the Android Runtime library module to an existing app
4-
position: 0
4+
position: 6
55
slug: debug-android-runtime
66
---
77

@@ -21,15 +21,15 @@ In certain scenarios where runtime errors occur, the debug info provided by the
2121

2222
### 1. Create a new NativeScript application using one of the following commands depending on your language/technology preference:
2323

24-
NativeScript with Angular:
24+
NativeScript with Angular:
2525

2626
`tns create debug-android-runtime --ng`
2727

28-
NativeScript with TypeScript:
28+
NativeScript with TypeScript:
2929

3030
`tns create debug-android-runtime --tsc`
3131

32-
NativeScript with plain JavaScript:
32+
NativeScript with plain JavaScript:
3333

3434
`tns create debug-android-runtime`
3535

@@ -116,7 +116,7 @@ The symbols can be found in the cloned android runtime repo in: `<android-runtim
116116

117117
![Set CPP Breakpoint](set-cpp-runtime-breakpoint.png)
118118

119-
* Run Debug
119+
* Run Debug
120120

121121
![Run In Debug](hit-debug.png)
122122

docs/core-concepts/android-runtime/advanced-topics/execution-flow.md

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,91 +2,91 @@
22
nav-title: "Execution Flow"
33
title: "Execution Flow"
44
description: "NativeScript Android Runtime Execution Flow"
5-
position: 1
5+
position: 0
66
---
77

88
# Application Workflow
99

10-
Android Runtime
10+
Android Runtime
1111
---
1212
_Disclaimer: The author of this article assumes that you are familiar with the core concepts of [NativeScript](http://docs.nativescript.org/) and the [NativeScript Android Runtime](../overview.md)_
1313

1414
The Android Runtime is built on top of **[Google's V8 JavaScript Virtual Machine](#googles-v8)**. Pre-generated **[Metadata](#metadata-generator)** is embedded in the resulting application and as a result we get very efficient native access, while the **[Binding Generator](#binding-generator)** component takes care of the creation of custom Java classes build-time to extend Java/Android class functionality or serve as proxy.
15-
15+
1616
---
17-
17+
1818
## Google's V8
1919
V8 is the JavaScript Engine which compiles and executes the JavaScript code. It takes advantage of the [Just-In-Time Compilation technique](http://whatis.techtarget.com/definition/just-in-time-compiler-JIT) to process JavaScript code with great efficiency. [Read more.](https://developers.google.com/v8/)
20-
20+
2121
## JNI
2222
JNI is the **Java Native Interface** that provides means for Java code to interact with native code. Put shortly - it allows a Java program to invoke functions in another C/C++ program and vice versa. In the context of a NativeScript application JNI is the communicational layer between the V8 JavaScript Engine and the platform - Java/Android code. [Read more.](http://developer.android.com/training/articles/perf-jni.html)
23-
24-
## Metadata Generator
23+
24+
## Metadata Generator
2525
The [Metadata Generator](../metadata/overview.md) uses Apache Commons BCEL to iterate through all native dependencies added to the project, and exposes their public API to the Android Runtime.
26-
26+
2727
## Bindings Generator
2828
The [Bindings Generator](../generator/overview.md) is responsible for the dynamic generation of implemented classes and interfaces. When the user implements an Android object, a custom Java proxy object is created. The process of generating Java classes at build-time is highly optimized.
29-
29+
3030
---
31-
32-
# Application Workflow
31+
32+
# Application Workflow
3333
Much like in a Node.js application, a NativeScript application needs a virtual machine that understands the JavaScript code we write. Google's V8 parses JavaScript already, but would not know of Java syntax or objects. That is why pre-generated metadata is necessary. The Metadata Generator creates binaries of all Android types at build-time, that will later be consumed by the Android Runtime and exposed to JavaScript. But JavaScript and Java are two entirely different programming languages with no means to communicate directly. The Android Runtime uses JNI to bridge the gap between V8 and Android's Dalvik, allowing the two to send instructions back and forth despite their discrepancies where data types and objects are concerned.
34-
34+
3535
Let's look at an example where, much like in JavaScript, we can write an event and attach it to a view (button) to respond to user's actions.
36-
36+
3737
```javascript
3838
// ... code omitted for brevity
39-
39+
4040
var Color = android.graphics.Color; // 1
4141
var colors = [Color.BLUE, Color.RED, Color.MAGENTA, Color.YELLOW, Color.parseColor("#FF7F50")] // 2
4242
var taps = 0;
43-
43+
4444
var button = new android.widget.Button(this); // 3
4545
button.setText("Hit me"); // 4
4646
layout.addView(button);
47-
47+
4848
button.setOnClickListener(new android.view.View.OnClickListener({ // 5
4949
onClick: function() {
5050
button.setBackgroundColor(colors[taps % colors.length]);
5151
taps++;
5252
}}));
53-
53+
5454
// ... code omitted for brevity
5555
```
56-
56+
5757
In plain* JavaScript in the browser that same code would look like this *(Depending on your choice of framework, if any, some lines may differ):
58-
58+
5959
```javascript
6060
var colors = ["#0000FF", "#FF0000", "#FF00FF", "#FFFF00", "#FF7F50"];
6161
var taps = 0;
62-
63-
var button = document.createElement("button");
62+
63+
var button = document.createElement("button");
6464
var btnText = document.createTextNode("Hit me");
6565
button.appendChild(btnText);
6666
document.body.appendChild(button);
67-
67+
6868
button.addEventListener("click", function() {
6969
button.style.background = colors[taps % colors.length];
7070
taps++;
7171
});
7272
```
73-
73+
7474
And now let's go through the steps of exactly what happens when we write the above:
75-
75+
7676
1. We access a native [Class](https://docs.oracle.com/javase/tutorial/java/concepts/class.html) through JavaScript and save it to a variable for the purposes of writing shorter code later. From here on we can call any of the class Color's public static methods, access its public fields and constants, or make an instance of it, if a public constructor is present. On the following line we save the [constants' values](http://developer.android.com/reference/android/graphics/Color.html) in an array, as they have different representations than in JavaScript.
7777
2. As mentioned above, we get access to a [Class object](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html)'s methods, and we take advantage of that to produce another color that was not in the predefined values of the class.
7878
3. We create a new instance of an Android button. In normal scenarios of writing JavaScript none of it would make sense, but in the context of NativeScript that is a totally valid syntax, and will in fact work and create a button for us. Similar to how we handled colors earlier, we can save the Button class in a variable and use it to make a Button instance - `var Button = android.widget.Button; var button = new Button(this);`. This not only creates an object in JavaScript, but in Android as well. What this means is that any changes made to the object using the relevant API will be reflected on the button that will appear on the screen of your device.
7979
4. We then proceed to set the button instance's text to a string. A marshalling service will take care of converting any arguments passed to functions to their respective data type representation in the Java world, in our case - JavaScript `string` to Java `java.lang.String`. The button's content will be changed to "Hit me".
8080
5. Finally, we add event listener to our button. Again, similar to the way we do it in JavaScript, we need to provide a callback that will be executed when an action - a click, hold, load, etc., occurs. The way this is done using the NativeScript Android Runtime is by passing our button instance's method `setOnClickListener` an argument which contains the callback implementation.
8181

8282
---
83-
83+
8484
# Execution Flow Illustration
8585
Now that we know how to access the native API, let's have a look at the common execution flow of an application written in NativeScript.
86-
Triggering an event in Android will always be handled by the Dalvik Virtual Machine ([ART](https://en.wikipedia.org/wiki/Android_Runtime)) which acts as the first responder in a native application. Any implementation included in the body of the event will then be executed by the NativeScript Android runtime, and the result of the operation returned to JavaScript. If a change to a native variable or view is made, instructions will again go through Dalvik.
86+
Triggering an event in Android will always be handled by the Dalvik Virtual Machine ([ART](https://en.wikipedia.org/wiki/Android_Runtime)) which acts as the first responder in a native application. Any implementation included in the body of the event will then be executed by the NativeScript Android runtime, and the result of the operation returned to JavaScript. If a change to a native variable or view is made, instructions will again go through Dalvik.
8787

8888
**Note**: If no changes to native variables are present as a result of the execution of the callback (for example, when a local JavaScript variable that doesnt hold a reference to an Android object is modified - a number, a string, an array of JavaScript Objects, etc.), no calls to Dalvik will be made.
89-
89+
9090
Execution Flow illustration:
9191
![How a NativeScript program's execution flow looks like on Android devices](app_process.png)
9292

docs/core-concepts/android-runtime/advanced-topics/extend-application-activity.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
nav-title: "Extending Application and Activity"
33
title: "Extending Application and Activity"
44
description: "Extending Application and Activity for Android"
5-
position: 2
5+
position: 1
66
---
77

88
# Extending Application and Activity
9-
This article describes how to create custom `android.app.Application` and `android.support.v7.app.AppCompatActivity` implementations in a NativeScript application.
9+
This article describes how to create custom `android.app.Application` and `android.support.v7.app.AppCompatActivity` implementations in a NativeScript application.
1010

1111
> **Note**: Demo code below is taken from the Android Extend demos for [plain JavaScript](https://github.com/NativeScript/nativescript-dev-webpack/blob/master/demo/JavaScriptApp/app/activity.android.js), [TypeScript](https://github.com/NativeScript/nativescript-dev-webpack/blob/master/demo/TypeScriptApp/app/activity.android.ts) or [Angular](https://github.com/NativeScript/nativescript-dev-webpack/blob/master/demo/AngularApp/app/activity.android.ts) applications.
1212
@@ -30,11 +30,11 @@ The following steps are needed to create custom native `android.app.Application`
3030
```javascript
3131
const superProto = android.app.Application.prototype;
3232

33-
// the first parameter of the `extend` call defines the package and the name for the native *.JAVA file generated.
33+
// the first parameter of the `extend` call defines the package and the name for the native *.JAVA file generated.
3434
android.app.Application.extend("org.myApp.Application", {
3535
onCreate: function() {
3636
superProto.onCreate.call(this);
37-
37+
3838
// At this point modules have already been initialized
3939

4040
// Enter custom initialization code here
@@ -47,12 +47,12 @@ The following steps are needed to create custom native `android.app.Application`
4747
});
4848
```
4949
```typescript
50-
// the `JavaProxy` decorator specifies the package and the name for the native *.JAVA file generated.
50+
// the `JavaProxy` decorator specifies the package and the name for the native *.JAVA file generated.
5151
@JavaProxy("org.myApp.Application")
5252
class Application extends android.app.Application {
5353
public onCreate(): void {
5454
super.onCreate();
55-
55+
5656
// At this point modules have already been initialized
5757
5858
// Enter custom initialization code here
@@ -152,7 +152,7 @@ The core modules ship with a default `android.support.v7.app.AppCompatActivity`
152152
public isNativeScriptActivity;
153153
154154
private _callbacks: AndroidActivityCallbacks;
155-
155+
156156
public onCreate(savedInstanceState: android.os.Bundle): void {
157157
// Set the isNativeScriptActivity in onCreate (as done in the original NativeScript activity code)
158158
// The JS constructor might not be called because the activity is created from Android.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
title: "Gradle Hooks"
3+
description: "Extensibility hooks for the gradle build"
4+
position: 2
5+
slug: gradle-hooks
6+
---
7+
8+
# Gradle Hooks
9+
10+
NativeScript uses gradle to build android applications. The gradle build files are part of the application template that comes from the android runtime package. Sometimes, if you want to use any external plugins or libraries you need to add some code to the gradle files. There are several locations for gradle files that can be used for adding your code. They are applied in the build process in the following order:
11+
12+
`App_Resources/Android/buildscript.gradle`\
13+
plugins' `buildscript.gradle`\
14+
`App_Resources/Android/before-plugins.gradle`\
15+
plugins' `include.gradle`\
16+
`App_Resources/Android/app.gradle`
17+
18+
## app.gradle
19+
20+
In this file you can set the default Android configurations like `minSdkVersion` and `targetSdkVersion`. You can also add your native dependencies here. In most of the cases, this is the file which you should use when you need to add some gradle code in your application. The reason for applying `app.gradle` last is that it should be able to override any properties or settings that any plugin might have set.
21+
22+
```Groovy
23+
android {
24+
defaultConfig {
25+
minSdkVersion 17
26+
generatedDensities = []
27+
}
28+
aaptOptions {
29+
additionalParameters "--no-version-vectors"
30+
}
31+
}
32+
dependencies {
33+
implementation 'com.android.support:recyclerview-v7:+'
34+
}
35+
```
36+
37+
## Plugins' include.gradle
38+
39+
Every NativeScript plugin, which contains native Android dependencies, should also provide a valid `include.gradle` file located in the root of its `platforms/android` directory. This `include.gradle` file must meet the following requirements:
40+
41+
* It must contain its own [configuration](http://developer.android.com/tools/building/configuring-gradle.html).
42+
* It may contain native dependencies required to build the plugin properly.
43+
* Any native dependencies should be available in [jcenter](https://bintray.com/bintray/jcenter) or in the Android SDK installed on your machine, if you want it to work out of the box. You can see an example of a compile dependency [here](https://github.com/NativeScript/nativescript-fresco/blob/master/platforms/android/include.gradle).
44+
45+
This file can be used for many kinds of native project configuration, depending on the purpose of the plugin. You can find more information [here](http://developer.android.com/tools/building/configuring-gradle.html)
46+
47+
```Groovy
48+
// optional elements
49+
dependencies {
50+
compile "groupName:pluginName:ver"
51+
}
52+
```
53+
54+
## before-plugins.gradle
55+
56+
Sometimes you need to change something right before the execution of all the `include.gradle` files of your project's plugins. An example is setting `googlePlayServicesVersion` when you use **nativescript-google-maps-sdk** plugin. If you set the value with the following code in the `app.gradle` file:
57+
58+
```Groovy
59+
ext {
60+
googlePlayServicesVersion = "10.0.1"
61+
}
62+
```
63+
it will be too late for the plugin to receive it, as all plugins' `include.gradle`s will have been applied beforehand. So, the correct place to set this property will be in `before-plugins.gradle` instead.
64+
65+
## buildscript.gradle
66+
67+
When using a plugin like [this one](https://docs.embrace.io/docs/android-integration-guide) there are some **buildscript** configurations which need to be added in the application's **build.gradle** file. Unfortunately this cannot be achieved through the `app.gradle` file nor through plugin's `include.gradle` files. They are being applied too late in the build process and the changes in the **buildscript** do not have any effect.
68+
In this case a `buildscript.gradle` file needs to be used. These files can be placed either in `App_Resources/Android` folder in the NativeScript application, or in the `platforms/android` folder of a plugin. All such files will be applied to the **buildscript** of the application's `build.gradle`.
69+
70+
```Gradle
71+
repositories {
72+
google()
73+
jcenter()
74+
}
75+
dependencies {
76+
classpath 'embrace-io:embrace-swazzler:3.1.6'
77+
}
78+
```

docs/core-concepts/android-runtime/advanced-topics/marking-mode-none.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Optimizing Performance Using markingMode: none"
33
description: "How to enable markingMode:none in your NativeScript mobile app and prevent potential problems"
4-
position: 4
4+
position: 3
55
slug: marking-mode-none
66
---
77

@@ -13,7 +13,7 @@ The code inside `tns-core-modules` and all plugins published by the NativeScript
1313

1414
## Benefits and drawbacks of using markingMode: none
1515

16-
The biggest benefit of setting `markingMode` to `none` is a more responsive app – an app that does not slow down if you use it for an extended amount of time.
16+
The biggest benefit of setting `markingMode` to `none` is a more responsive app – an app that does not slow down if you use it for an extended amount of time.
1717
The main drawbacks are:
1818
- It is up to the plugin developer to manage the plugin-related memory correctly. There might be plugins that do not support the feature and could crash the app with a "cleared reference" exception.
1919
- It is up to the app developer to manage the app memory correctly. The app code itself might also need to be updated in order to keep JS object references and prevent unwanted collection.
@@ -29,7 +29,7 @@ First, to instruct any app to use this feature we need to add the following in t
2929
```
3030
If the app behaves correctly after this change - great. Sometimes, however, some sporadic errors/crashes occur, especially related to memory management, like any of the following:
3131
- `Error: com.tns.NativeScriptException: Attempt to use cleared object reference id=<some-object-id-number>`
32-
- `The JavaScript instance no longer has available Java instance counterpart`
32+
- `The JavaScript instance no longer has available Java instance counterpart`
3333

3434
In such cases additional work has to be done. Have in mind the problem could be either in the app code, or in some plugin(s) used by the app. In both cases the resolution is identical.
3535

@@ -45,7 +45,7 @@ var callback = new android.native.NCallback({ // native interface
4545
android.native.Executor.printWithDelay(callback, 3s);
4646
```
4747

48-
The implementor is enclosed by the callback implementation, but with `markingMode: none` enabled the framework no longer takes care of finding out that connection. So, when GC happens in V8 or in Android the `implementor` instance (or its native representation) is GC'ed. This can result in either Java or JavaScript instance missing and upon calling of the `callback` an "Attempt to use cleared object reference" or "JavaScript instance no longer has available Java counterpart" error is very likely to occur.
48+
The implementor is enclosed by the callback implementation, but with `markingMode: none` enabled the framework no longer takes care of finding out that connection. So, when GC happens in V8 or in Android the `implementor` instance (or its native representation) is GC'ed. This can result in either Java or JavaScript instance missing and upon calling of the `callback` an "Attempt to use cleared object reference" or "JavaScript instance no longer has available Java counterpart" error is very likely to occur.
4949

5050
### Solution
5151

docs/core-concepts/android-runtime/advanced-topics/memory-management.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Memory Management"
33
description: "Best practices and recommendations on how to improve the performance of your NativeScript mobile app by tuning the memory management"
4-
position: 4
4+
position: 5
55
slug: android-memory-management
66
---
77

0 commit comments

Comments
 (0)