Native development with JavaScript

 

Andrey Kucherenko

 

ReactNative

 

No DOM

 

 JavaScript engine in a separate background thread

 





$ npm install -g react-native-cli
/usr/local/bin/react-native -> /usr/local/lib/node_modules/react-native-cli/index.js
react-native-cli@0.1.4 /usr/local/lib/node_modules/react-native-cli
└── prompt@0.2.14 (revalidator@0.1.8, pkginfo@0.3.0, read@1.0.7, winston@0.8.3, utile@0.2.1)





$ react-native init MentoringProject
This will walk you through creating a new React Native project in /Users/Andrii_Kucherenko/Workspace/MentoringProject
 
> utf-8-validate@1.2.1 install /Users/Andrii_Kucherenko/Workspace/MentoringProject/node_modules/react-native/node_modules/ws/node_modules/utf-8-validate
> node-gyp rebuild

  CXX(target) Release/obj.target/validation/src/validation.o
  SOLINK_MODULE(target) Release/validation.node
 
> bufferutil@1.2.1 install /Users/Andrii_Kucherenko/Workspace/MentoringProject/node_modules/react-native/node_modules/ws/node_modules/bufferutil
> node-gyp rebuild

  CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
  SOLINK_MODULE(target) Release/bufferutil.node
 
> spawn-sync@1.0.13 postinstall /Users/Andrii_Kucherenko/Workspace/MentoringProject/node_modules/react-native/node_modules/yeoman-generator/node_modules/cross-spawn/node_modules/spawn-sync
> node postinstall

 
> fsevents@1.0.0 install /Users/Andrii_Kucherenko/Workspace/MentoringProject/node_modules/react-native/node_modules/babel/node_modules/chokidar/node_modules/fsevents
> node-pre-gyp install --fallback-to-build

[fsevents] Success: "/Users/Andrii_Kucherenko/Workspace/MentoringProject/node_modules/react-native/node_modules/babel/node_modules/chokidar/node_modules/fsevents/lib/binding/Release/node-v14-darwin-x64/fse.node" is installed via remote
react-native@0.11.2 node_modules/react-native
├── absolute-path@0.0.0
├── progress@1.1.8
├── graceful-fs@4.1.2
├── stacktrace-parser@0.1.3
├── wordwrap@1.0.0
├── react-timer-mixin@0.13.3
├── underscore@1.7.0
├── image-size@0.3.5
├── bser@1.0.0 (node-int64@0.4.0)
├── semver@4.3.6
├── debug@2.1.0 (ms@0.6.2)
├── yargs@1.3.2
├── chalk@1.0.0 (escape-string-regexp@1.0.3, ansi-styles@2.1.0, supports-color@1.3.1, strip-ansi@2.0.1, has-ansi@1.0.3)
├── promise@7.0.4 (asap@2.0.3)
├── optimist@0.6.1 (wordwrap@0.0.3, minimist@0.0.10)
├── immutable@3.7.5
├── worker-farm@1.3.1 (xtend@4.0.0, errno@0.1.4)
├── source-map@0.1.31 (amdefine@1.0.0)
├── sane@1.3.0 (watch@0.10.0, minimist@1.2.0, exec-sh@0.2.0, fb-watchman@1.6.0, walker@1.0.7, minimatch@0.2.14)
├── rebound@0.0.12
├── uglify-js@2.4.16 (uglify-to-browserify@1.0.2, async@0.2.10, optimist@0.3.7, source-map@0.1.34)
├── connect@2.8.3 (methods@0.0.1, uid2@0.0.2, fresh@0.1.0, pause@0.0.1, cookie-signature@1.0.1, qs@0.6.5, bytes@0.2.0, buffer-crc32@0.2.1, cookie@0.1.0, send@0.1.2, formidable@1.0.14)
├── regenerator@0.8.36 (private@0.1.6, through@2.3.8, recast@0.10.25, commoner@0.10.3, esprima-fb@15001.1.0-dev-harmony-fb, defs@1.1.0)
├── ws@0.8.0 (options@0.0.6, ultron@1.0.2, utf-8-validate@1.2.1, bufferutil@1.2.1)
├── jstransform@11.0.1 (object-assign@2.1.1, base62@1.1.0, source-map@0.4.4, esprima-fb@15001.1.0-dev-harmony-fb, commoner@0.10.3)
├── module-deps@3.5.6 (inherits@2.0.1, shallow-copy@0.0.1, duplexer2@0.0.2, minimist@0.2.0, parents@1.0.1, concat-stream@1.4.10, subarg@0.0.1, readable-stream@1.1.13, through2@0.4.2, resolve@0.7.4, stream-combiner2@1.0.2, browser-resolve@1.9.1, JSONStream@0.7.4, detective@3.1.0)
├── joi@5.1.0 (topo@1.0.3, isemail@1.2.0, hoek@2.16.3, moment@2.10.6)
├── yeoman-environment@1.2.7 (escape-string-regexp@1.0.3, log-symbols@1.0.2, diff@1.4.0, text-table@0.2.0, untildify@2.1.0, mem-fs@1.1.0, globby@2.1.0, grouped-queue@0.3.0, lodash@3.10.1, inquirer@0.8.5)
├── yeoman-generator@0.20.3 (read-chunk@1.0.1, detect-conflict@1.0.0, yeoman-welcome@1.0.1, path-is-absolute@1.0.0, path-exists@1.0.0, yeoman-assert@2.1.0, rimraf@2.4.3, async@1.4.2, text-table@0.2.0, mime@1.3.4, xdg-basedir@2.0.0, user-home@2.0.0, dargs@4.0.1, istextorbinary@1.0.2, nopt@3.0.4, run-async@0.1.0, mkdirp@0.5.1, shelljs@0.5.3, cli-table@0.3.1, through2@2.0.0, pretty-bytes@2.0.1, diff@2.1.2, glob@5.0.14, dateformat@1.0.11, underscore.string@3.2.2, findup-sync@0.2.1, mem-fs-editor@2.0.4, github-username@2.0.0, class-extend@0.1.1, download@4.2.1, html-wiring@1.2.0, gruntfile-editor@1.0.0, sinon@1.17.1, cross-spawn@2.0.0, lodash@3.10.1, inquirer@0.8.5)
├── react-tools@0.14.0-beta1 (commoner@0.10.3)
├── babel@5.8.21 (slash@1.0.0, path-is-absolute@1.0.0, path-exists@1.0.0, fs-readdir-recursive@0.1.2, convert-source-map@1.1.1, commander@2.8.1, source-map@0.4.4, output-file-sync@1.1.1, glob@5.0.14, lodash@3.10.1, chokidar@1.1.0)
└── babel-core@5.8.21 (slash@1.0.0, try-resolve@1.0.1, babel-plugin-remove-console@1.0.1, babel-plugin-remove-debugger@1.0.1, babel-plugin-jscript@1.0.4, babel-plugin-inline-environment-variables@1.0.1, babel-plugin-property-literals@1.0.1, babel-plugin-eval@1.0.1, babel-plugin-react-constant-elements@1.0.3, babel-plugin-member-expression-literals@1.0.1, babel-plugin-undefined-to-void@1.1.6, trim-right@1.0.1, to-fast-properties@1.0.1, babel-plugin-react-display-name@1.0.3, path-is-absolute@1.0.0, path-exists@1.0.0, shebang-regex@1.0.0, babel-plugin-constant-folding@1.0.1, fs-readdir-recursive@0.1.2, babel-plugin-proto-to-assign@1.0.4, babel-plugin-dead-code-elimination@1.0.2, babel-plugin-runtime@1.0.7, private@0.1.6, globals@6.4.1, esutils@2.0.2, convert-source-map@1.1.1, js-tokens@1.0.1, babel-plugin-undeclared-variables-check@1.0.2, home-or-tmp@1.0.0, debug@2.2.0, detect-indent@3.0.1, line-numbers@0.2.0, babylon@5.8.23, resolve@1.1.6, is-integer@1.0.6, repeating@1.1.3, output-file-sync@1.1.1, source-map@0.4.4, minimatch@2.0.10, bluebird@2.10.1, source-map-support@0.2.10, json5@0.4.0, regexpu@1.3.0, lodash@3.10.1, regenerator@0.8.35, core-js@1.2.0)
Setting up new React Native app in /Users/Andrii_Kucherenko/Workspace/MentoringProject
   create .flowconfig
   create .gitignore
   create .watchmanconfig
   create index.ios.js
   create index.android.js
   create ios/main.jsbundle
   create ios/MentoringProject/AppDelegate.h
   create ios/MentoringProject/AppDelegate.m
   create ios/MentoringProject/Base.lproj/LaunchScreen.xib
   create ios/MentoringProject/Images.xcassets/AppIcon.appiconset/Contents.json
   create ios/MentoringProject/Info.plist
   create ios/MentoringProject/main.m
   create ios/MentoringProjectTests/MentoringProjectTests.m
   create ios/MentoringProjectTests/Info.plist
   create ios/MentoringProject.xcodeproj/project.pbxproj
   create ios/MentoringProject.xcodeproj/xcshareddata/xcschemes/MentoringProject.xcscheme
   create android/app/build.gradle
   create android/app/proguard-rules.pro
   create android/app/src/main/AndroidManifest.xml
   create android/app/src/main/res/values/strings.xml
   create android/app/src/main/res/values/styles.xml
   create android/build.gradle
   create android/gradle.properties
   create android/settings.gradle
   create android/app/src/main/res/mipmap-hdpi/ic_launcher.png
   create android/app/src/main/res/mipmap-mdpi/ic_launcher.png
   create android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
   create android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
   create android/gradle/wrapper/gradle-wrapper.jar
   create android/gradle/wrapper/gradle-wrapper.properties
   create android/gradlew
   create android/gradlew.bat
   create android/app/src/main/java/com/mentoringproject/MainActivity.java
To run your app on iOS:
   Open /Users/Andrii_Kucherenko/Workspace/MentoringProject/ios/MentoringProject.xcodeproj in Xcode
   Hit Run button
To run your app on Android:
   Have an Android emulator running, or a device connected
   cd /Users/Andrii_Kucherenko/Workspace/MentoringProject
   react-native run-android





// index.ios.js

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
} = React;




// index.ios.js

var MentoringProject = React.createClass({
  render: function() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.ios.js
        </Text>
        <Text style={styles.instructions}>
          Press Cmd+R to reload,{'\n'}
          Cmd+D or shake for dev menu
        </Text>
      </View>
    );
  }
});




// index.ios.js

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});







// index.ios.js

AppRegistry.registerComponent('MentoringProject', () => MentoringProject);
 
var React = require('react-native');
 
var {
    StyleSheet,
    View,
    Text,
    Component
   } = React;
 
var styles = StyleSheet.create({
    description: {
        fontSize: 20,
        backgroundColor: 'white'
    },
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center'
    }
});
 
class Featured extends Component {
    render() {
        return (
  	    <View style={styles.container}>
	        <Text style={styles.description}>
        	  Featured Tab
	        </Text>
	    </View>
        );
    }
}
module.exports = Featured;
'use strict';
 
var React = require('react-native');
var SearchResults = require('./SearchResults');
var {
    StyleSheet,
    View,
    Text,
    Component,
    TextInput,
    TouchableHighlight,
    ActivityIndicatorIOS
    } = React;
 
var styles = StyleSheet.create({
    ...
});
 
class SearchBooks extends Component {
 
    constructor(props) {
        super(props);
        this.state = {
            bookAuthor: '',
            bookTitle: '',
            isLoading: false,
            errorMessage: ''
        };
    }
 
 
    searchBooks() {
        this.fetchData();
    }

    render() {
        var spinner = this.state.isLoading ?
            ( <ActivityIndicatorIOS
                hidden='true'
                size='large'/> ) :
            ( <View/>);
        return (
            <View style={styles.container}>
                <Text style={styles.instructions}>Search by book title and/or author</Text>
                <View>
                    <Text style={styles.fieldLabel}>Book Title:</Text>
                    <TextInput style={styles.searchInput} onChange={this.bookTitleInput.bind(this)}/>
                </View>
                <View>
                    <Text style={styles.fieldLabel}>Author:</Text>
                    <TextInput style={styles.searchInput} onChange={this.bookAuthorInput.bind(this)}/>
                </View>
                <TouchableHighlight style={styles.button}
                                    underlayColor='#f1c40f'
                                    onPress={this.searchBooks.bind(this)}>
                    <Text style={styles.buttonText}>Search</Text>
                </TouchableHighlight>
                {spinner}
                <Text style={styles.errorMessage}>{this.state.errorMessage}</Text>
            </View>
        );
    }
 
    bookTitleInput(event) {
        this.setState({ bookTitle: event.nativeEvent.text });
    }
 
    bookAuthorInput(event) {
        this.setState({ bookAuthor: event.nativeEvent.text });
    }
 
    

 
    searchBooks() {
        this.fetchData();
    }

    render() {
        var spinner = this.state.isLoading ?
            ( <ActivityIndicatorIOS
                hidden='true'
                size='large'/> ) :
            ( <View/>);
        return (
            <View style={styles.container}>
                <Text style={styles.instructions}>Search by book title and/or author</Text>
                <View>
                    <Text style={styles.fieldLabel}>Book Title:</Text>
                    <TextInput style={styles.searchInput} onChange={this.bookTitleInput.bind(this)}/>
                </View>
                <View>
                    <Text style={styles.fieldLabel}>Author:</Text>
                    <TextInput style={styles.searchInput} onChange={this.bookAuthorInput.bind(this)}/>
                </View>
                <TouchableHighlight style={styles.button}
                                    underlayColor='#f1c40f'
                                    onPress={this.searchBooks.bind(this)}>
                    <Text style={styles.buttonText}>Search</Text>
                </TouchableHighlight>
                {spinner}
                <Text style={styles.errorMessage}>{this.state.errorMessage}</Text>
            </View>
        );
    }
 
    bookTitleInput(event) {
        this.setState({ bookTitle: event.nativeEvent.text });
    }
 
    bookAuthorInput(event) {
        this.setState({ bookAuthor: event.nativeEvent.text });
    }
 
    
'use strict';

var React = require('react-native');
var Featured = require('./Featured');
var Search = require('./Search');

var {
    AppRegistry,
    TabBarIOS,
    Component
   } = React;

class BookSearch extends Component {

    constructor(props) {
        super(props);
        this.state = {
            selectedTab: 'featured'
        };
    }

    render() {
        return (
            <TabBarIOS selectedTab={this.state.selectedTab}>
                <TabBarIOS.Item
                    selected={this.state.selectedTab === 'featured'}
                    icon={{uri:'featured'}}
                    onPress={() => {
                        this.setState({
                            selectedTab: 'featured'
                        });
                    }}>
                    <Featured/>
                </TabBarIOS.Item>
                <TabBarIOS.Item
                    selected={this.state.selectedTab === 'search'}
                    icon={{uri:'search'}}
                    onPress={() => {
                        this.setState({
                            selectedTab: 'search'
                        });
                    }}>
                    <Search/>
                </TabBarIOS.Item>
            </TabBarIOS>
        );
    }
}

AppRegistry.registerComponent('BookSearch', () => BookSearch);




npm install -g nativescript


//Create Project
tns create MyApp


//Navigate to the directory that contains your newly created project and add platforms
tns platform add android
tns platform add ios


//-------------------------------------------------------------------
// Develop your awesome application in your favorite IDE and hardware
//-------------------------------------------------------------------

// Run project on device…
tns run android
tns run ios

//...or run project in emulator
tns run android --emulator
tns run ios --emulator

Cylon.JS

 

Hardware platforms




var Cylon = require('cylon');

Cylon.robot({
  connections: {
    edison: { adaptor: 'intel-iot' }
  },

  devices: {
    led: { driver: 'led', pin: 13 }
  },

  work: function(my) {
    every((1).second(), my.led.toggle);
  }
}).start();



var Cylon = require('cylon');
Cylon.robot({

    connections: {
        edison: {adaptor: 'intel-iot'},
        sphero: {adaptor: 'sphero', port: "/dev/rfcomm0"}
    },

    devices: {
        sphero: {driver: 'sphero', connection: 'sphero'}
    },

    work: function (my) {
        var color = process.argv[2] || 0xFF0000;

        my.sphero.color(color);
     
    }
});
Cylon.start();



var Cylon = require('cylon');

Cylon.robot({
  connections: {
    edison: { adaptor: 'intel-iot'},
    sphero: { adaptor: 'sphero', port: '/dev/rfcomm0' }
  },

  devices: {
    led: { driver: 'led', pin: 13, connection: 'edison' },
    sphero: { driver: 'sphero', connection: 'sphero' }
  },

  work: function(my) {
    my.sphero.stop();
    my.sphero.detectCollisions();
    my.sphero.on('collision', function() {
      my.led.toggle();
    });
  }
}).start();


var Cylon = require('cylon');

Cylon.robot({
  connections: {
    sphero: { adaptor: 'sphero', port: '/dev/rfcomm0' }
  },

  devices: {
    sphero: { driver: 'sphero' }
  },

  work: function(my) {
    var flag = true;
    var color = 0x00FF00,
        bitFilter = 0xFFFF00;

    console.log("Setting up Collision Detection...");

    my.sphero.on("collision", function() {
      console.log("Collision:");
      color = color ^ bitFilter;
      console.log("Color: " + (color.toString(16)) + " ");
      my.sphero.color(color);
    });

    my.sphero.detectCollisions();    

    every((2).second(), function () {
     my.sphero.roll(60, flag ? 190 : 10);
     flag = !flag;
    });
  }
}).start();

Parrot Bebop




var Cylon = require('cylon');

Cylon.robot({
  connections: {
    bebop: { adaptor: 'bebop' }
  },

  devices: {
    drone: { driver: 'bebop' }
  },

  work: function(my) {
    my.drone.takeOff();
    after((5).seconds(), my.drone.land);
  }
}).start();



var arDrone = require('ar-drone');
var client  = arDrone.createClient();
client.createRepl();


$ node repl.js
// Make the drone takeoff
drone> takeoff()
true
// Wait for the drone to takeoff
drone> clockwise(0.5)
0.5
// Let the drone spin for a while
drone> land()
true
// Wait for the drone to land

Questions?

 

Native development with JavaScript

By Andrey Kucherenko

Native development with JavaScript

  • 1,851