Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Save Captured Images in a NativeScript Angular Application to Couchbase

DZone's Guide to

Save Captured Images in a NativeScript Angular Application to Couchbase

NativeScript devs using Angular can send image captures to a database, Couchbase Lite here. If database saves are the direction you want to go, here's how to do it.

· Database Zone
Free Resource

Learn how to move from MongoDB to Couchbase Server for consistent high performance in distributed environments at any scale.

I get a particular set of questions quite a bit when it comes to mobile applications, the first being how to save captured images, and the second being how to sync them between devices or a remote database. Since I’m a huge fan of NativeScript for Android and iOS development, I thought it would be great to share one of many possible examples of solving this problem.

We’re going to see how to capture images in a NativeScript application using Angular and save those captured images to Couchbase Lite, an embedded device-level database.

Going forward, it is important to note that there are many ways to save images or any other file data within a mobile application. For example, you could save them in a database or you can save them on the file system. We’re going to be saving them directly into the database in this example, but do your research on what strategy will work best for you.

In the animated image above, we are presented with the ability to capture images. Things are a little different in a simulator, but on a device, the camera will open. After capturing an image it will be presented on the screen and saved into Couchbase Lite as a base64 formatted string.

The Requirements

There aren’t many requirements when it comes to being successful with this guide. At a minimum you’ll need the following:

  • NativeScript CLI
  • Android SDK for Android and Xcode for iOS

To be able to build for Android you’ll need the Android SDK and to be able to build for iOS you’ll need Xcode, which is only available on macOS computers. For this particular guide, no remote instance of Couchbase Server is necessary.

Creating a Fresh NativeScript with Angular Project

With the prerequisites installed and ready to go, we need to create a fresh project somewhere on our computer.

From the NativeScript CLI, execute the following:

tns create photo-project --ng


The above command will create a new Angular project, hence the --ng flag.

Before we start developing, we will need to install the Couchbase plugin for NativeScript. This can be done by executing the following:

tns plugin add nativescript-couchbase


While we can technically start developing the application, there is one more order of business to take care of. On iOS it is a requirement to explain each of the permissions being used. Being able to take photos or use the gallery is a permission request, so we have to explain.

Open the project’s app/App_Resources/iOS/Info.plist file and include the following:

<key>NSPhotoLibraryUsageDescription</key>
<string>Photo Library Access Warning</string>


The above will prevent any errors during compile time or run time. Now we can safely start developing our Android and iOS mobile application.

Developing the Core Application Logic and User Interface

Before we start adding our own code, let’s strip out a bunch of the boilerplate template code that ships when creating a new NativeScript with an Angular project.

This is going to be a single page application, so we need to remove any of the pre-existing navigation routes. Start by opening the project’s app/app.routing.ts file and make it look like the following:

import { NgModule } from "@angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { Routes } from "@angular/router";

const routes: Routes = [];

@NgModule({
    imports: [NativeScriptRouterModule.forRoot(routes)],
    exports: [NativeScriptRouterModule]
})
export class AppRoutingModule { }


The only thing we did was remove the routes from the routes array. Technically, we can remove this file, but it is easier just to strip out what we’re not going to use.

Now open the project’s app/app.module.ts file and make the TypeScript look like the following:

import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { AppRoutingModule } from "./app.routing";
import { AppComponent } from "./app.component";


@NgModule({
    bootstrap: [
        AppComponent
    ],
    imports: [
        NativeScriptModule,
        AppRoutingModule
    ],
    declarations: [
        AppComponent
    ],
    providers: [],
    schemas: [
        NO_ERRORS_SCHEMA
    ]
})
export class AppModule { }


Notice in the above we’ve removed any reference to the MVC files that were previously routes. This includes HTML, TypeScript, and the Angular service that was provided.

When it comes to adding new content, we’re going to focus on the TypeScript logic first, then move into the HTML UI. Open the project’s app/app.component.ts file and include the following:

import { Component, OnInit } from "@angular/core";
import { Couchbase } from "nativescript-couchbase";
import * as Camera from "camera";
import * as ImageSource from "image-source";

@Component({
    selector: "ns-app",
    templateUrl: "app.component.html",
})
export class AppComponent implements OnInit {

    public database: any;
    public images: Array<any>;

    public constructor() {
        this.database = new Couchbase("image-database");
        this.database.createView("images", "1", function(document, emitter) {
            if(document.type && document.type == "image") {
                emitter.emit(document._id, document);
            }
        });
        this.images = [];
    }

    public ngOnInit() {
        let rows = this.database.executeQuery("images");
        for(let i = 0; i < rows.length; i++) {
            this.images.push(ImageSource.fromBase64(rows[i].image));
        }
    }

    public capture() {
        Camera.takePicture({ width: 300, height: 300, keepAspectRatio: true, saveToGallery: false }).then(picture => {
            let base64 = picture.toBase64String("png", 70);
            this.database.createDocument({
                "type": "image",
                "image": base64,
                "timestamp": (new Date()).getTime()
            });
            this.images.push(picture);
        }, error => {
            console.dump(error);
        });
    }

}


A lot is happening in the above code so we’re going to break it down.

We had previously downloaded the Couchbase plugin for NativeScript, but now we need to import it along with other things:

import { Couchbase } from "nativescript-couchbase";
import * as Camera from "camera";
import * as ImageSource from "image-source";


The camera functionality is already included with NativeScript, we just need to import it. When it comes to manipulating the camera data, the ImageSource is what we’ll use.

Within the AppComponent class we have two variables:

private database: any;
public images: Array<any>;


The database will hold our open Couchbase Lite instance and the images will hold all saved images that will be presented on the screen.

Within the constructor method we open our database, create a view that we can later query, and initialize the array that will store our images.

public constructor() {
    this.database = new Couchbase("image-database");
    this.database.createView("images", "1", function(document, emitter) {
        if(document.type && document.type == "image") {
            emitter.emit(document._id, document);
        }
    });
    this.images = [];
}


The view that we’re creating will return all NoSQL documents that have a property called type that is set to image which represents to us that it is one of the possible images for displaying on the screen.

Because data should never be loaded in the constructor method, we take things to the ngOnInit method:

public ngOnInit() {
    let rows = this.database.executeQuery("images");
    for(let i = 0; i < rows.length; i++) {
        this.images.push(ImageSource.fromBase64(rows[i].image));
    }
}


The ngOnInit method triggers after the constructor method and it will query the view that had been previously created. Each document saved will have a property called imagethat contains base64 image data. This model is based on our design.

After obtaining the base64 data it is converted into an ImageSource and added to our array to be displayed on the screen.

public capture() {
    Camera.takePicture({
        width: 300,
        height: 300,
        keepAspectRatio: true,
        saveToGallery: false
    }).then(picture => {
        let base64 = picture.toBase64String("png", 70);
        this.database.createDocument({
            "type": "image",
            "image": base64,
            "timestamp": (new Date()).getTime()
        });
        this.images.push(picture);
    }, error => {
        console.dump(error);
    });
}


The above capture method is called via a button press in our HTML. It will launch the camera with a few settings defined.

Upon a successful capture, the picture will be converted to base64 and a NoSQL document will be created along with various information sitting next to the base64 data.

Not so bad right?

Now we want to take a look at the HTML markup that goes with this logic. Open the project’s app/app.component.html file and include the following:

<ActionBar title="{N} Couchbase Photos">
    <ActionItem text="Capture" ios.position="right" (tap)="capture()"></ActionItem>
</ActionBar>
<StackLayout>
    <Image *ngFor="let image of images" [src]="image"></Image>
</StackLayout>


In the above HTML we have an actionbar with a button that will trigger the camera. Within the core content of the page we have a loop that will go through each image in the array and display it on the screen.

Conclusion

You just saw how to create a basic image capturing application with NativeScript and Angular that saves image data directly into Couchbase Lite NoSQL documents as base64 encoded strings. Next time around we’re going to see how to synchronize this image data between devices and a remote database instance.

Want to deliver a whole new level of customer experience? Learn how to make your move from MongoDB to Couchbase Server.

Topics:
angular ,database ,nativescript ,couchbase ,tutorial

Published at DZone with permission of Nic Raboy, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}