Saturday, 4 June 2016

Post 52: detect device motion with Ionic

In this post I'll show you how to detect the motion of your device with Ionic framework.

First create an Ionic project and then add a platform. How to do this with android is explained here.

I created a "tabs" ionic project. But you can choose whatever project type ("blank", "sidemenu") you want.
Download the ng-cordova zip file here. After downloading unzip and find the file "ng-cordova.min.js". The file is located at "ng-cordova-master\dist\". Put that file into the following folder of our project: "yourProject\www\js\".

Add this line in your index.html
<script src="js/ng-cordova.min.js"></script>
<script src="cordova.js"></script>

Install the following two plugins:

cordova plugin add cordova-plugin-device-motion
cordova plugin add cordova-plugin-whitelist

In your app.js add "ngCordova" to your service array:

angular.module('starter', ['ionic', 'starter.controllers', '', 'ngCordova'])

Add this to your index.html:
    <ion-pane ng-controller="MotionController">
        <ion-header-bar class="bar-stable">
            <h1 class="title">Start Watching Device Motion</h1>

            <div class="list">
                <label class="item item-input">
                    <span class="input-label">Frequency</span>
                    <input type="text" placeholder="0" ng-model="options.frequency">
            <button class="button button-full button-positive" ng-click="startWatching()">
                Start Measurement
            <button class="button button-full button-positive" ng-click="stopWatching()">
                Stop Measurement
            <h2>X: {{measurements.x}}</h2>
            <h2>Y: {{measurements.y}}</h2>
            <h2>Z: {{measurements.z}}</h2>

And add this into the header of your index.html

<meta http-equiv="Content-Security-Policy" content="default-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval' *; style-src  'self' 'unsafe-inline' *">

In your controller.js add the MotionController:
.controller('MotionController', function($scope, $cordovaDeviceMotion, $ionicPlatform) {
// watch Acceleration options $scope.options = { frequency: 100, // Measure every 100ms deviation : 25 // We'll use deviation to determine the shake event, best values in the range between 25 and 30 }; // Current measurements $scope.measurements = { x : null, y : null, z : null, timestamp : null } // Previous measurements $scope.previousMeasurements = { x : null, y : null, z : null, timestamp : null } // Watcher object $ = null; // Start measurements when Cordova device is ready $ionicPlatform.ready(function() { //Start Watching method $scope.startWatching = function() { // Device motion configuration $ = $cordovaDeviceMotion.watchAcceleration($scope.options); // Device motion initilaization $, function(error) { console.log('Error'); },function(result) { // Set current data $scope.measurements.x = result.x; $scope.measurements.y = result.y; $scope.measurements.z = result.z; $scope.measurements.timestamp = result.timestamp; // Detecta shake $scope.detectShake(result); }); }; // Stop watching method $scope.stopWatching = function() { $; } // Detect shake method $scope.detectShake = function(result) { //Object to hold measurement difference between current and old data var measurementsChange = {}; // Calculate measurement change only if we have two sets of data, current and old if ($scope.previousMeasurements.x !== null) { measurementsChange.x = Math.abs($scope.previousMeasurements.x, result.x); measurementsChange.y = Math.abs($scope.previousMeasurements.y, result.y); measurementsChange.z = Math.abs($scope.previousMeasurements.z, result.z); } // If measurement change is bigger then predefined deviation if (measurementsChange.x + measurementsChange.y + measurementsChange.z > $scope.options.deviation) { $scope.stopWatching(); // Stop watching because it will start triggering like hell console.log('Shake detected'); // shake detected setTimeout($scope.startWatching(), 1000); // Again start watching after 1 sex // Clean previous measurements after succesfull shake detection, so we can do it next time $scope.previousMeasurements = { x: null, y: null, z: null } } else { // On first measurements set it as the previous one $scope.previousMeasurements = { x: result.x, y: result.y, z: result.z } } } }); $scope.$on('$ionicView.beforeLeave', function(){ $; // Turn off motion detection watcher });