How To Set Up Quick Actions With 3D Touch For Your Ionic App

30 October 2015Ionic, Cordova, 3D Touch

3D Touch is a new hardware feature on the iPhone 6S (Plus) that detects how much pressure a user puts on the screen. Developers can use this to define Quick Actions that will be displayed when the user touches the app icon in the Home Screen.

In this tutorial we'll have a look at how to set up Quick Actions for Ionic apps.

###What will we be building? We will be building a simple note-taking app that will have a New Note Quick Action.

When you start the app it will display the Notes view and from there you can tap the + button to go to the New Note modal view.

When the user taps the New Note Quick Action on the app from the Home Screen it will load the app and launch the New Note modal view.

Quick Action App Demo

Before we start coding, let's have a look at the types of Quick Actions.

###Dynamic vs Static There are 2 types of Quick Actions:

  1. Static, these will be available immediately after you install an app.
  2. Dynamic, these will be available after you've launched the app the first time. As the name suggests, these Quick Actions can be changed depending on content in the app.

You can set up a maximum of 4 Quick Actions for your app.

We will be using a Cordova plugin to create a Dynamic Quick Action in our JavaScript code.

If you want to create Static Quick Actions, you'll have to do this in the Info.plist file in your XCode project. See the documentation of the Cordova plugin on how to do that.

###Code Time Let's start by creating a blank Ionic app:

$ ionic start ionic-tutorial-quickactions blank

In index.html we'll add the templates for the Notes view and the New Note modal view.

<body ng-app="starter" ng-controller="NoteController as vm">
	<ion-pane>
	  <ion-header-bar class="bar-stable">
		<h1 class="title">Notes</h1>
		<div class="buttons">
		  <button ng-click="vm.showNewNoteModal()" class="button button-icon icon ion-android-add"></button>
		</div>
	  </ion-header-bar>
	  <ion-content>
		<ion-list>
		  <ion-item ng-repeat="n in vm.notes">
			{{ n.description }}
		  </ion-item>
		</ion-list>
	  </ion-content>
	</ion-pane>

	<script id="new-note.html" type="text/ng-template">
	  <ion-modal-view>
		<ion-header-bar>
		  <h1 class="title">New Note</h1>
		</ion-header-bar>
		<ion-content>
		  <div class="list list-inset">
			<label class="item item-input">
			  <input type="text" placeholder="Description" ng-model="vm.note.description">
			</label>
		  </div>
		  <div class="padding">
			<button ng-click="vm.saveNote()" class="button button-block button-positive activated">Save</button>
		  </div>
		</ion-content>
	  </ion-modal-view>
	</script>
</body>

In note.controller.js we'll create the NoteController.

angular.module('starter').controller('NoteController', ['$scope', '$rootScope', '$ionicModal', NoteController]);

function NoteController($scope, $rootScope, $ionicModal) {
	var vm = this;
	vm.notes = [];

	// Initialize the modal view.
	$ionicModal.fromTemplateUrl('new-note.html', {
		scope: $scope,
		animation: 'slide-in-up'
	}).then(function(modal) {
		vm.modal = modal;
	});

	vm.showNewNoteModal = function() {
		vm.note = {};
		vm.modal.show();
	};

	vm.saveNote = function() {
		vm.notes.push(vm.note);
		vm.modal.hide();
	};

	$scope.$on('$destroy', function() {
		vm.modal.remove();
	});

	// TODO: We'll add code later to respond to the Quick Action

	return vm;
}

We won't be persisting the notes in this tutorial. If you want to know how to persist data locally, have a look at my tutorials for PouchDB and LokiJS.

OK, so now we should have a working app without the Quick Action, let's load the app and check if it's working as expected.

$ ionic serve

###Configure Quick Action When you created the app with the Ionic CLI it should have automatically added the iOS platform. If that didn't happen add it now.

$ ionic platform ios

Next, we'll need to install the plugin cordova-plugin-3dtouch.

$ cordova plugin add cordova-plugin-3dtouch

Create a new service QuickActionService in quickaction.service.js to set up the Quick Action for our app.

angular.module('starter').factory('QuickActionService', ['$rootScope', '$q', QuickActionService]);

function QuickActionService($rootScope, $q) {

	function check3DTouchAvailability() {
		return $q(function(resolve, reject) {
			if (window.ThreeDeeTouch) {
				window.ThreeDeeTouch.isAvailable(function (available) {
					resolve(available);
				});
			} else {
				reject();
			}
		});
	}

	function configure() {
		// Check if 3D Touch is supported on the device
		check3DTouchAvailability().then(function(available) {

				if (available) { 	// Comment out this check if testing in simulator

					// Configure Quick Actions
					window.ThreeDeeTouch.configureQuickActions([
						{
							type: 'newNote',
							title: 'New Note',
							subtitle: '',
							iconType: 'compose'
						}
					]);

					// Set event handler to check which Quick Action was pressed
					window.ThreeDeeTouch.onHomeIconPressed = function(payload) {
						if (payload.type == 'newNote') {
							$rootScope.$broadcast('newNoteQuickAction');
						}
					};
				}
		})
	}

	return {
		configure: configure
	};
}

There are a couple of things happening here so let's break it down.

####Check if 3D Touch is available First, we need to check if 3D Touch is supported on the device. We're checking if the ThreeDeeTouch plugin is available, this is automatically loaded on the device because we installed the plugin cordova-plugin-3dtouch.

The next step is to call the isAvailable function which takes in a callback function.

####Create the Quick Action The configure function is responsible for configuring the Quick Action. You can put any text you want in the type, title and subtitle fields.

To configure the icon you can either use iconType (predefined icons) or iconTemplate (provide your own icon). Check the plugin documentation for details on how to use this.

####Check which Quick Action was pressed The onHomeIconPressed callback will be invoked when the user taps on the Quick Action. We can see which Quick Action it was by checking the payload.type.

We are using $rootscope.$broadcast to notify the NoteController that the New Note Quick Action was pressed.

Let's not forget to call the QuickActionService.configure function in app.js when the device is ready.

angular.module('starter', ['ionic'])
.run(function($ionicPlatform, QuickActionService) {
  $ionicPlatform.ready(function() {
    // existing code left out for readability

    QuickActionService.configure();
  });
})

###Display Modal View Now let's add the code to the NotesController to show the New Note modal view when the Quick Action is pressed.

$rootScope.$on('newNoteQuickAction', function() {
	vm.showNewNoteModal();
});

###We're done! To test this you'll need to run the app on a device that supports 3D Touch.

$ ionic run ios

You can use Quick Actions on an older device, without 3D Touch, if it's jailbroken. I haven't tried it myself, but you can read more [here]((http://ios.wonderhowto.com/how-to/get-3d-touch-older-iphones-use-quick-actions-home-screen-0165363/).

###Testing in the Simulator The iOS simulators don't support 3D Touch at the moment, but there is a little hack that will allow you to test Quick Actions in the simulator.

Get and build SBShortcutMenuSimulator.

$ git clone https://github.com/DeskConnect/SBShortcutMenuSimulator.git
$ cd SBShortcutMenuSimulator
$ make

We'll have to comment out the check for 3D Touch availability in quickactions.service.js, because the simulator will return false and that will prevent the configuration of the Quick Action.

if (available) { 	// Comment out this check if testing in simulator

Start the app in the simulator.

$ ionic emulate ios

Run these commands in the directory SBShortcutMenuSimulator.

$ xcrun simctl spawn booted launchctl debug system/com.apple.SpringBoard --environment DYLD_INSERT_LIBRARIES=$PWD/SBShortcutMenuSimulator.dylib
$ xcrun simctl spawn booted launchctl stop com.apple.SpringBoard

You should now be looking at the home screen on the simulator. To see the Quick Action on the app, run the following command.

$ echo 'com.ionictutorial.quickactions' | nc 127.0.0.1 8000

Make sure you use your app's bundle identifier. You can find this in config.xml.

###Closing Thoughts This was a very simple implementation of a Quick Action, but you can imagine that there will be use cases where you want to jump to a state that is deeper into the navigation stack of your app.

In that case, you won't have any navigation history built up in the app, so how will you navigate "back" through the app? There is a nice solution for this problem described in this article about deep-linking in Ionic.

###Useful Resources

WRITTEN BY
profile
Ashteya Biharisingh

Full stack developer who likes to build mobile apps and read books.