Skip to content

Commit

Permalink
Merge pull request NativeScript#767 from NativeScript/PetyaSotirova/A…
Browse files Browse the repository at this point in the history
…ndroidRuntimeDocsLatest

Latest content from the android-runtime-docs repo
  • Loading branch information
PetyaSotirova authored May 9, 2017
2 parents 763e083 + e2a9672 commit b4486fa
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 76 deletions.
7 changes: 1 addition & 6 deletions runtimes/android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ The repository contains the raw content files. To see the HTML representation of
* [Overview](./overview.md)
* [Requirements](./requirements.md)
* Getting Started
* [Hello World Application](./getting-started/hello-world.md)
* [Project Structure](./getting-started/project-structure.md)
* [Modules & Require](./getting-started/modules.md)
* Metadata
Expand All @@ -21,15 +20,11 @@ The repository contains the raw content files. To see the HTML representation of
* [Extending Classes and Interfaces](./generator/extend-class-interface.md)
* [How Extend Works](./generator/how-extend-works.md)
* [Gotchas](./generator/gotchas.md)
* Using External Libraries
* [Simple JAR Libs](./external-libs/jars.md)
* [Libraries With Resources](./external-libs/resource-libs.md)
* TypeScript Support
* Extending Android Types
* Gotchas
* Debugging
* [Debugging NativeScript for Android](./debug/debug-cli.md)
* [Advanced Debugging NativeScript for Android](./debug/debug-eclipse.md)
* Advanced Topics
* [Execution Flow](./getting-started/execution-flow.md)
* [Execution Flow](./advanced-topics/execution-flow.md)
* [V8 Heap Snapshots](./advanced-topics/V8-heap-snapshots.md)
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The following steps are needed to create custom native `android.app.Application`
var Application = android.app.Application.extend("org.myApp.Application", {
onCreate: function() {
superProto.onCreate.call(this);

// At this point modules have already been initialized

// Enter custom initialization code here
Expand All @@ -53,9 +53,8 @@ The following steps are needed to create custom native `android.app.Application`
class Application extends android.app.Application {
protected onCreate(): void {
super.onCreate();
// initialize the modules with the custom application object
application.android.init(this);
// At this point modules have already been initialized
// Enter custom initialization code here
}
Expand All @@ -69,8 +68,6 @@ The following steps are needed to create custom native `android.app.Application`
}
```

>Note the `application.init` call within the `onCreate` override. This is needed by the core modules to cache the application context and perform bootstraping logic before the main `Activity` is created.

3. Modify the `application` entry within the `AndroidManifest.xml` file found in the `<application-name>app/App_Resources/Android/` folder:

```xml
Expand Down
2 changes: 1 addition & 1 deletion runtimes/android/advanced-topics/memory-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ The described approaches are not mutually exclusive. You can combine them as it
* Avoid allocating many large objects at once
* Avoid allocating objects in loops

Be causios when you write closures as it often hard to observe object retentions along all the reference chain.
Be cautious when you write closures as it often hard to observe object retentions along all the reference chain.
22 changes: 22 additions & 0 deletions runtimes/android/advanced-topics/v8-flags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
nav-title: "V8 Flags"
title: "V8 Flags"
description: "Tuning with V8 flags"
position: 5
---

# Tuning V8

V8 comes with a set of controlling flags that may be useful for a fine-grained tuning. Currently, we use `--expose_gc` flag to expose global `gc()` function which comes handy in advanced memory management scenarios. You can set these flags in `package.json` configuration file.

```
{
...
"android": {
"v8Flags": "--expose_gc"
}
...
}
```

For example, here are all the flags in V8 `5.5.372` [https://github.com/v8/v8/blob/5.5.372/src/flag-definitions.h](https://github.com/v8/v8/blob/5.5.372/src/flag-definitions.h)
Binary file modified runtimes/android/debug/debug-cli-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 20 additions & 23 deletions runtimes/android/debug/debug-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ nav-title: "Debug"
title: "Debug"
description: "Debugging NativeScript for Android"
position: 1
previous_url: /debug-eclipse
---

# Overview

Since NativeScript for Android embeds a JavaScript virtual machine (namely [Google's V8](https://code.google.com/p/v8/)) to process the JavaScript code, it also takes advantage of the debugger tools available for this virtual machine. These are [Node Inspector](https://github.com/node-inspector/node-inspector) and [Chrome Developer Tools](https://developer.chrome.com/devtools/index).
Since NativeScript for Android embeds a JavaScript virtual machine (namely [Google's V8](https://code.google.com/p/v8/)) to process the JavaScript code, it also takes advantage of the debugger tools available for this virtual machine - the [Chrome Developer Tools](https://developer.chrome.com/devtools/index).

> The article assumes that you are familiar with [JavaScript debugging in the Chrome Developer Tools](https://developer.chrome.com/devtools/docs/javascript-debugging). The required node-inspector package is installed by the CLI. You will also need the Chrome web browser installed locally.
> The article assumes that you are familiar with [JavaScript debugging in the Chrome Developer Tools](https://developer.chrome.com/devtools/docs/javascript-debugging). You will need the Chrome web browser installed locally.
The current implementation supports two major scenarios:

Expand All @@ -21,18 +22,24 @@ The current implementation supports two major scenarios:
The following command will build, deploy and run the application with the debugger attached:

```bash
tns debug android --debug-brk
tns debug android
```
Behind the scenes the `debug` command, together with the `--debug-brk` option, will build and start the application and then it will find an available port and enable V8's debugger on that port. Finally, it will start Node Inspector and launch Chrome browser.
Behind the scenes the `debug` command will build and start the target application and then it will find an available port and enable V8's debugger on that port. Finally, you'll get a url starting with `chrome-devtools://` to copy/paste into Chrome to start the debug session.

![Image1](./debug-cli-screenshot.png)

> In this case the debugger will automatically break at the first JavaScript statement.

# Features

- Breakpoint debugging, stepping
- *Inline* source maps support for transpiled code
- Console evaluation


# Setting breakpoints in JavaScript
The global `debugger` statement causes V8 to stop program execution and start a debugging session at the line where it was called. It is equivalent to setting a "manual" breakpoint in the Sources tab of Chrome DevTools.
The global `debugger` sets a V8 breakpointIn the script source. It is equivalent to setting a "manual" breakpoint in the Sources tab of Chrome DevTools.

> See [this article](https://developer.chrome.com/devtools/docs/console#setting-breakpoints-in-javascript) for more information.
> See [this article](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/debugger) for more information.
# Attach the debugger

Expand All @@ -42,30 +49,20 @@ If you have a running application you can attach the debugger with the following
tns debug android --start
```

> As in the previous scenario, the `debug` command will configure the V8 debugger port, forward the port, start Node Inspector and launch Chrome browser. It will however will not automatically break and will only hit manually set breakpoints.
> As in the previous scenario, the `debug` command will configure the V8 debugger port, forward the port, and output a url to paste into Chrome.
# Detach the debugger
You can detach the debugger from an already debugged application using the following command:

```bash
tns debug android --stop
```

# Miscellaneous
Detaching the debugger is as simple as closing the chrome-devtools tab.

You can check whether a debugger is enabled with the following command:
# Notes

```bash
tns debug android --get-port
```
> The current implementation has hard-coded 30 seconds timeout for establishing a connection between the command line tool and the device/emulator.
It will return the current debugger port, 0 otherwise.

> The current implementation has hard-coded 30 seconds timeout for establishing a connection between the command line tool and the device/emulator.
> Debugging sources different than JavaScript (TypeScript, CoffeeScript, etc.) is only possible when source maps are inlined by the transpiler.
# See Also
* [Node Inspector](https://github.com/node-inspector/node-inspector).
* [Chrome Developer Tools](https://developer.chrome.com/devtools/index).
* [JavaScript debugging](https://developer.chrome.com/devtools/docs/javascript-debugging).
* [debugger; statement](https://developer.chrome.com/devtools/docs/console#setting-breakpoints-in-javascript)

* [debugger; statement](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/debugger)
98 changes: 76 additions & 22 deletions runtimes/android/generator/extend-class-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,40 @@ MyButton btn = new MyButton(context);

Here is how the above is done in NativeScript:

```javascript
``` JavaScript
var constructorCalled = false;
var MyButton = android.widget.Button.extend({
//constructor
init: function() {
constructorCalled = true;
},

setEnabled: function(enabled) {
this.super.setEnable(enabled);
}
});
var btn = new MyButton(context);
//constructorCalled is true here
//constructor
init: function() {
constructorCalled = true;
},

setEnabled: function(enabled) {
this.super.setEnable(enabled);
}
});

var btn = new MyButton(context);
// constructorCalled === true
```
``` TypeScript
class MyButton extends android.widget.Button.extend
static constructorCalled: boolean = false;
//constructor
init() {
MyButton.constructorCalled = true;

// necessary when extending TypeScript constructors
return global.__native(this);
}

setEnabled(enabled : boolean): void {
this.super.setEnable(enabled);
}
}

let btn = new MyButton(context);
// MyButton.constructorCalled === true
```

> **Note:** In the above setEnabled function the `this` keyword points to the JavaScript object that proxies the extended native instance. The `this.super` property provides access to the base class method implementation.
Expand All @@ -54,7 +74,14 @@ button.setOnClickListener(new View.OnClickListener() {
});
```

```javascript
``` JavaScript
button.setOnClickListener(new android.view.View.OnClickListener({
onClick: function() {
// Perform action on click
}
}));
```
``` TypeScript
button.setOnClickListener(new android.view.View.OnClickListener({
onClick: function() {
// Perform action on click
Expand Down Expand Up @@ -98,11 +125,14 @@ public class MyVersatileCopywriter implements Printer, Copier, Writer {
}
```

The same result can be achieved in NativeScript by extending(./how-extend-works.md) any valid object that inherits [Java Object](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html), and declaring an **interfaces** array in the implementation as shown below:
The same result can be achieved in NativeScript by [extending]({%slug how-extend-works}) any valid object that inherits [Java Object](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html).

- In JavaScript - Declare an **interfaces** array in the implementation
- Using Typescript syntax - apply a **decorator** to the extended class (note `@Interfaces([...]`))

Using Javascript syntax - attach `interfaces` array to implementation object of the extend call

```javascript
``` JavaScript
var MyVersatileCopyWriter = java.lang.Object.extend({
interfaces: [com.a.b.Printer, com.a.b.Copier, com.a.b.Writer], /* the interfaces that will be inherited by the resulting class */
print: function() { ... }, /* implementing the 'print' methods from Printer */
Expand All @@ -112,19 +142,24 @@ var MyVersatileCopyWriter = java.lang.Object.extend({
toString: function() { ... } /* override `java.lang.Object's` `toString */
});
```

Using Typescript syntax - apply a **decorator** to the extended class (note `@Interfaces([...]`))

```typescript
``` TypeScript
@Interfaces([com.a.b.Printer, com.a.b.Copier, com.a.b.Writer]) /* the interfaces that will be inherited by the resulting MyVersatileCopyWriter class */
class MyVersatileCopyWriter extends java.lang.Object {
constructor() {
return global.__native(this);
}

print() { ... }
copy() { ... }
write() { ... }
writeLine() { ... }
}
```


> When implementing Java interfaces in NativeScript, it is necessary to provide implementation (declare the methods - `print`, `copy`, `write`, `writeLine`) for **every** method present in the interfaces, otherwise compilation will fail. If you do not want to fully implement an interface you need to declare empty functions. Functions with empty bodies are considered valid method implementations (`print: function() {}`).

## Limitations
* Implementing two interfaces with the same method signature will generate just 1 method. It is the implementor's responsibility to define how the method will behave for both interfaces
* Implementing two interfaces with the same *method name*, *parameter number*, but **different return type** (`void a()` vs `boolean a()`) will result in a compilation error
Expand All @@ -133,14 +168,14 @@ class MyVersatileCopyWriter extends java.lang.Object {
### Notes
> Java method overloads are handled by the developer by explicitly checking the `arguments` count of the invoked function
```javascript
``` JavaScript
var MyVersatileCopyWriter = ...extend({
...
print: function() {
var content = "";
var offset = 0;

if(arguments.length == 2) {
if (arguments.length == 2) {
offset = arguments[1];
}

Expand All @@ -151,8 +186,27 @@ var MyVersatileCopyWriter = ...extend({
...
})
```
``` TypeScript
class MyVersatileCopyWriter extends ... {
constructor() {
return global.__native(this);
}
...
print() {
let content = "";
let offset = 0;

> When implementing Java interfaces in NativeScript, it is necessary to provide implementation (declare the methods - `print`, `copy`, `write`, `writeLine`) for **every** method present in the interfaces, otherwise compilation will fail. If you do not want to fully implement an interface you need to declare empty functions. Functions with empty bodies are considered valid method implementations (`print: function() {}`).
if (arguments.length == 2) {
offset = arguments[1];
}

content = arguments[0];

// do stuff
}
...
}
```



Expand Down
1 change: 1 addition & 0 deletions runtimes/android/generator/how-extend-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ nav-title: "How Extend Works"
title: "How Extend Works"
description: "NativeScript Android Runtime Extend Workflow"
position: 3
slug: how-extend-works
---

# The Extend Function
Expand Down
4 changes: 2 additions & 2 deletions runtimes/android/metadata/accessing-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var androidPkg = android;
var androidViewPkg = android.view;
```

> **Note:** You may not use APIs that are not present in the metadata. By default the Android Runtime comes with prebuilt metadata for Android [API level 23](https://developer.android.com/about/versions/marshmallow/index.html).
> **Note:** You may not use APIs that are not present in the metadata. By default, if `--compileSdk` argument isn't provided while building, metadata will be built for the latest Android [Platform SDK](https://developer.android.com/about/versions/nougat/index.html) installed on the workstation.
# Proxies
The JavaScript objects that lie behind the Android APIs are called *Proxies*. There are two types of proxies:
Expand All @@ -40,7 +40,7 @@ Class proxies may be instantiated much like in Android:
var file = new java.io.File("/path/to/myfile.txt");
```

The result of the call will create a native java.io.File instance on the Android side and a special hollow Object on the JavaScript side. This special object knows how to invoke methods and access fields on the corresponding native instance. For example we may retrieve the path value of the above created `File` like:
The result of the call will create a native java.io.File instance on the Android side and a special hollow Object on the JavaScript side. This special object knows how to invoke methods and access fields on the corresponding native instance. For example we may retrieve the path value of the above created `File` using the corresponding `File` class API like:

```javascript
var path = file.getPath();
Expand Down
Loading

0 comments on commit b4486fa

Please sign in to comment.