Our website is made possible by displaying online advertisements to our visitors. Please consider supporting us by disabling your ad blocker.

Request Android Permissions In NativeScript Using Angular

TwitterFacebookRedditLinkedInHacker News

With every version of Android comes more security measures dropped into place. For example, in Android 6+ the user needs to grant permissions when doing certain activities, such as using the camera. These security measures are more aggressive than the previous form of asking permissions in the manifest file.

So what if we want to prompt the user to grant permissions at a time other than when trying to use the feature that requires the permissions? For example, asking for camera permissions when the application loads, rather than when we try to use the camera feature of the application?

We’re going to see how to request permissions in an Android NativeScript project with Angular.

If you’ve dabbled with Android development before, whether that be with Java or NativeScript, you’ll be familiar with the AndroidManifest.xml file that ships with every project. This is where you typically define the permissions your application requires. This does not change as you will need to define your permissions up front regardless of the Android version.

Our goal is to define where we want the second phase of permission granting to happen.

NativeScript Request Android Permissions

Take a look at the above animated image. In it we are requesting permission to use the camera even though we have no intention of actually using the camera.

So let’s create an example application!

Create a New NativeScript with Angular Mobile Project

For simplicity, we’re going to create a fresh NativeScript project that uses Angular. Assuming you have the NativeScript CLI installed and configured, execute the following:

tns create permissions-project --ng

The --ng flag above indicates we are creating an Angular project rather than a vanilla NativeScript Core project.

Going forward, it is important to note that iOS doesn’t require permissions in the same sense that Android does. For this reason, this stuff only applies to Android. However, iOS will assume true on everything we design which will not hinder our development.

To request permission for things at runtime, we need a plugin for the job. Execute the following from the NativeScript CLI:

tns plugin add nativescript-permissions

With the project ready to go, we can now focus on the application.

Adding the Manifest Permissions

When it comes to Android permissions, our first stop should be the AndroidManifest.xml file found in the project’s app/App_Resources/Android path.

By default, your manifest file might look something like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="__PACKAGE__"
    android:versionCode="1"
    android:versionName="1.0">

    <supports-screens
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true"/>

    <uses-sdk
        android:minSdkVersion="17"
        android:targetSdkVersion="__APILEVEL__"/>

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:name="com.tns.NativeScriptApplication"
        android:allowBackup="true"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

        <activity
            android:name="com.tns.NativeScriptActivity"
            android:label="@string/title_activity_kimera"
            android:configChanges="keyboardHidden|orientation|screenSize"
            android:theme="@style/LaunchScreenTheme">

            <meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.tns.ErrorReportActivity"/>
    </application>
</manifest>

What we care about is the permissions section. As you can see, NativeScript already applies a few permissions by default:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>

A full list of Android permissions can be found in the official Android documentation. We want to work with the camera permissions, so we can add the following to our list:

<uses-permission android:name="android.permission.CAMERA"/>

As a fun fact, not all Android permissions require a two step grant. This means that some permissions only need to go into the manifest and that is enough. They will never be presented to the user at runtime. The camera permissions do not fall under the one step scenario.

Now that the AndroidManifest.xml file is updated, we can focus on our application logic.

Developing the Application Logic for Requesting Android Permissions

With a new NativeScript project comes a lot of boilerplate files and code that is overkill to what we’re after. We’re building a single page application, so we can strip out some things to prevent errors.

Open 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 { }

We’ve removed references to the components that came with our project. Likewise, we need to do the same in the project’s app/app.module.ts file:

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 { }

At this point we can focus our development on a singular page.

Open the project’s app/app.component.ts file and include the following TypeScript code. We’ll break it down after.

import { Component, OnInit } from "@angular/core";
import * as Permissions from "nativescript-permissions";

declare var android: any;

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

    public getCameraPermission() {
        Permissions.requestPermission(android.Manifest.permission.CAMERA, "Needed for connectivity status").then(() => {
            console.log("Permission granted!");
        }).catch(() => {
            console.log("Permission is not granted (sadface)");
        });
    }

}

A few things to notice in the above code.

First we’re importing the plugin that we had previously installed. Because we need to use Android specific permissions, we need to interface directly with the Android SDK classes. At this time there are no TypeScript type definitions available for the entire Android SDK, which is why we declare them as a wildcard using:

declare var android: any;

Within the AppComponent class we make use of the plugin, passing in the permission we want to request. Again, not all permissions need to be requested at runtime.

Permissions.requestPermission(android.Manifest.permission.CAMERA, "Needed for connectivity status").then(() => {
    console.log("Permission granted!");
}).catch(() => {
    console.log("Permission is not granted (sadface)");
});

If permissions were granted, the promise will resolve, otherwise it will reject.

It is important to note that it is necessary to always check if permissions were granted. The user can reject grants at any time via the Android OS settings.

Now let’s look at the UI. Open the project’s app/app.component.html file and include the following:

<ActionBar title="{N} Request Permissions"></ActionBar>
<StackLayout>
    <Button text="Camera" class="btn btn-primary" (tap)="getCameraPermission()"></Button>
</StackLayout>

The UI simply calls our function when the user taps the button. Nothing fancy at all.

Conclusion

You just saw how to request Android permissions at runtime in a NativeScript with Angular application. This is not a replacement to the AndroidManifest.xml file, but an addition because newer versions of Android require the users to grant permissions at runtime as well.

Like previously mentioned, not all permissions require a request at runtime. For example, I had previously written a tutorial for checking the internet connection, which required a permission. This permission did not need to be granted at runtime.

Nic Raboy

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in C#, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Unity. Nic writes about his development experiences related to making web and mobile development easier to understand.