Ionic Network don't return any data or response

I am trying to check the internet/network connection of the device using Network Plugin but it doesn't seem to work. It didn't even return any data or error messages on the console. Here is my code.

I am trying to check the internet/network connection of the device using Network Plugin but it doesn't seem to work. It didn't even return any data or error messages on the console. Here is my code.

import { Network } from '@ionic-native/network';

@Component({
templateUrl: 'app.html'
})

export class MyApp {

constructor(public platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar
public network: Network) {
this.initializeApp();
}

initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
this.checkInternetConnection();
}
}

checkInternetConnection() {
this.network.onDisconnect().subscribe(data => {
console.log('network was disconnected :-(');
}, error => console.log(error));

this.network.onConnect().subscribe(data => {
  console.log('network connected!');
  setTimeout(() => {
    console.log('woohoo!');
  }, 3000);
}, error => console.log(error));

}
}

I hope someone can help me. Thank you in advance 😊

Ionic 4, Angular 7 and Cordova Crop and Upload Image

Ionic 4, Angular 7 and Cordova Crop and Upload Image

The comprehensive step by step tutorial on crop, and upload Image using Ionic 4, Angular 7 and Cordova

The comprehensive step by step tutorial on crop, and upload Image using Ionic 4, Angular 7 and Cordova. We will use Native Ionic Cordova Crop, File Transfer plugins and it’s dependencies. In this tutorial, we will use our existing uploader API that you can find on our GitHub which it uses Node.js, Express.js, and Multer. Or, you can use your own backend or API that using HTML Form Encoding multipart/form-data. The scenario is in the Ionic 4 App, click the Camera button inside the preview image then it will open image picker. After image picked then it will go to cropping popup that you can crop anyway you like then upload to the API. After the successful upload, the Ionic 4 app will preview the Image by URL that saved to the API server.

Table of Contents:

The following tools, frameworks, and modules are required for this tutorial:

Before going to the main steps, we assume that you have to install Node.js. Next, upgrade or install new Ionic 4 CLI by open the terminal or Node command line then type this command.

sudo npm install -g ionic

You will get the latest Ionic CLI in your terminal or command line. Check the version by type this command.

ionic --version
4.12.0

1. Create a New Ionic 4, Angular 7 and Cordova App

To create a new Ionic 4 App, type this command in your terminal.

ionic start ionic4-crop blank --type=angular

If you see this question, just type N for because we will installing or adding Cordova later.

Install the free Ionic Appflow SDK and connect your app? (Y/n) N

Next, go to the newly created app folder.

cd ./ionic4-crop

As usual, run the Ionic 4 App for the first time, but before run as lab mode, type this command to install @ionic/lab.

npm install --save-dev @ionic/lab
ionic serve -l

Now, open the browser and you will the Ionic 4 App with the iOS, Android, or Windows view. If you see a normal Ionic 4 blank application, that’s mean you ready to go to the next steps.

2. Install and Configure Image Crop, File Transfer Plugins, and Dependencies

We will install all required plugins for this tutorial. First, we have to install Native Cordova plugins and Ionic 4 Angular 7 Modules by running these commands.

ionic cordova plugin add cordova-plugin-crop
npm install @ionic-native/crop
ionic cordova plugin add cordova-plugin-camera
npm install @ionic-native/camera
ionic cordova plugin add cordova-plugin-file-transfer
npm install @ionic-native/file-transfer
ionic cordova plugin add cordova-plugin-file
npm install @ionic-native/file

Next, open and edit src/app/app.module.ts then add these imports.

import { ImagePicker } from '@ionic-native/image-picker/ngx';

Add that import to @NgModule Providers.

providers: [
  StatusBar,
  SplashScreen,
  { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
  ImagePicker
],

3. Implementing Image Crop and File Upload/Transfer

We will be using the existing Home component or page to implementing Image Preview, Picker, Crop and Upload. For that, open and edit src/app/home/home.page.html then replace all HTML tags with these.

<ion-header>
&nbsp; <ion-toolbar>
&nbsp; &nbsp; <ion-title>
&nbsp; &nbsp; &nbsp; Ionic 4 Crop Upload
&nbsp; &nbsp; </ion-title>
&nbsp; </ion-toolbar>
</ion-header>

<ion-content padding>
&nbsp; <ion-card>
&nbsp; &nbsp; <img *ngIf="!fileUrl" src="assets/no-image.jpeg"/>
&nbsp; &nbsp; <img *ngIf="fileUrl" src="{{fileUrl}}"/>
&nbsp; &nbsp; <ion-card-content>
&nbsp; &nbsp; &nbsp; <ion-button color="medium" size="large" (click)="cropUpload()">
&nbsp; &nbsp; &nbsp; &nbsp; <ion-icon slot="icon-only" name="camera"></ion-icon>
&nbsp; &nbsp; &nbsp; </ion-button>
&nbsp; &nbsp; </ion-card-content>
&nbsp; </ion-card>
</ion-content>

Next, open and edit src/app/home/home.page.ts then add these imports.

import { Crop } from '@ionic-native/crop/ngx';
import { ImagePicker } from '@ionic-native/image-picker/ngx';
import { FileTransfer, FileUploadOptions, FileTransferObject } from '@ionic-native/file-transfer/ngx';

Inject those imports to the constructor.

constructor(private imagePicker: ImagePicker,
&nbsp; private crop: Crop,
&nbsp; private transfer: FileTransfer) { }

Add the variables for hold image URL and response data.

fileUrl: any = null;
respData: any;

Create a function for crop and upload an image file to the API server.

cropUpload() {
&nbsp; this.imagePicker.getPictures({ maximumImagesCount: 1, outputType: 0 }).then((results) => {
&nbsp; &nbsp; for (let i = 0; i < results.length; i++) {
&nbsp; &nbsp; &nbsp; &nbsp; console.log('Image URI: ' + results[i]);
&nbsp; &nbsp; &nbsp; &nbsp; this.crop.crop(results[i], { quality: 100 })
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .then(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newImage => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('new image path is: ' + newImage);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const fileTransfer: FileTransferObject = this.transfer.create();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const uploadOpts: FileUploadOptions = {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fileKey: 'file',
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fileName: newImage.substr(newImage.lastIndexOf('/') + 1)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fileTransfer.upload(newImage, 'http://192.168.0.7:3000/api/upload', uploadOpts)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.then((data) => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;console.log(data);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.respData = JSON.parse(data.response);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;console.log(this.respData);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.fileUrl = this.respData.fileUrl;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}, (err) => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;console.log(err);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;});
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; error => console.error('Error cropping image', error)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );
&nbsp; &nbsp; }
&nbsp; }, (err) => { console.log(err); });
}

As you can see, we use the IP address to access Express.js API from the device. The uploaded image file accessible from the device through [http://192.168.0.7:3000/images/filename](http://192.168.0.7:3000/images/filename "http://192.168.0.7:3000/images/filename") URL.

4. Run and Test Ionic 4, Angular 7 and Cordova App on iOS/Android Devices

We assume that you have cloned the Node.js, Express.js and Multer image uploader here https://github.com/didinj/node-express-image-uploader.git. Next, open a new Terminal or cmd-tab then go to the cloned Express image uploader.

npm install
nodemon

Next, to run on Android devices type this command while the device connected.

ionic cordova platform add android
ionic cordova run android

To run on iOS simulator or device, we have to build it first.

ionic cordova platform add ios
ionic cordova build ios

Then open and run the iOS app from the XCode. You will this view from your Android device or iOS simulator.

That it’s, the Ionic 4, Angular 7 and Cordova Crop and Upload Image tutorial. You can get the full source code from out GitHub.

How to Create Mobile Apps using Ionic 4, Angular 8 and Cordova?

How to Create Mobile Apps using Ionic 4, Angular 8 and Cordova?

In this Ionic 4 tutorial, we will show you how to create mobile apps quickly using Ionic 4, Angular 8, and Cordova

In this Ionic 4 tutorial, we will show you how to create mobile apps quickly using Ionic 4, Angular 8, and Cordova. In other words, this tutorial is the starting point to learn Ionic Framework, Angular, and Cordova. What you will get is not just create and running Ionic-Angular apps, but a little bit meaningful by displaying data in the Ionic list or grid, details, and Google maps. For more details about accessing data from REST API, Firebase, or Google Maps related, we have written the tutorials for you.

Table of Contents:

The following tools, frameworks, and modules are required for this tutorial:

  1. Node.js (Choose the recommended version)
  2. Ionic 4 with the type of Angular
  3. Cordova
  4. Terminal or Node Command Line
  5. IDE or Text Editor (We are using Visual Studio Code)
Step #1. Preparation

The first step of this tutorial prepares the environment to create the Ionic 4 apps. We will use the Mac OS of the Windows environment (choose one of them) and download the Node.js (recommended version). Install the downloaded Node.js to your Mac or Windows machine then check the version of Node.js by typing this command in the terminal or command line.

node -v
v10.15.1
npm -v
6.11.3

Next, we will install the Ionic CLI which now is version 5 and Cordova. Type this command in the terminal or command line to install it.

sudo npm i -g ionic cordova

As you see at the end of the Ionic and Cordova installation, we have Ionic-CLI 5 and Cordova 9.

+ [email protected]
+ [email protected]

Now, we have a ready to use Ionic Frameworks and Cordova environment in our machine.

Step #2. Create an Ionic 4 App with the Type of Angular

We will create an Ionic 4 app with the type of Angular and default template using Tabs. To do that, type this command in the terminal or command line.

ionic start ionic-tutorial tabs --type=angular

We will add Cordova later before we test the Ionic-Angular apps to the Android/iOS devices. Next, go to the newly created Ionic-Angular application then run the Ionic-Angular apps for the first time.

cd ./ionic-tutorial
ionic serve -l

If there's a question to install the @ionic/lab just type "Y". Now, the Ionic-Angular apps will open the default browser automatically and here the apps looks like in Lab mode.

Step #3. Modify Angular 8 Routes

We need to pass ID parameters to Tab2 and Tab3. So, we will modify the default or generated src/app/tabs/tabs-routing.module.ts. Just change the Angular routes constant to be like this.

const routes: Routes = [
  {
    path: 'tabs',
    component: TabsPage,
    children: [
      {
        path: 'tab1',
        children: [
          {
            path: '',
            loadChildren: () =>
              import('../tab1/tab1.module').then(m => m.Tab1PageModule)
          }
        ]
      },
      {
        path: 'tab2',
        children: [
          {
            path: '',
            loadChildren: () =>
              import('../tab2/tab2.module').then(m => m.Tab2PageModule)
          }
        ]
      },
      {
        path: 'tab2/:id',
        children: [
          {
            path: '',
            loadChildren: () =>
              import('../tab2/tab2.module').then(m => m.Tab2PageModule)
          }
        ]
      },
      {
        path: 'tab3',
        children: [
          {
            path: '',
            loadChildren: () =>
              import('../tab3/tab3.module').then(m => m.Tab3PageModule)
          }
        ]
      },
      {
        path: 'tab3/:id',
        children: [
          {
            path: '',
            loadChildren: () =>
              import('../tab3/tab3.module').then(m => m.Tab3PageModule)
          }
        ]
      },
      {
        path: '',
        redirectTo: '/tabs/tab1',
        pathMatch: 'full'
      }
    ]
  },
  {
    path: '',
    redirectTo: '/tabs/tab1',
    pathMatch: 'full'
  }
];
Step #4. Display Data to the Ionic List/Grid

To display data as Ionic List or Grid, first, we have to create an array of objects. We will put this array of objects in a separate file. For that, create a new Typescript file src/app/player.ts then add these lines of the export constant array.

export const Player = [
    { id: 1, name: 'Robbie Fowler', team: 'Liverpool', photo: 'assets/imgs/photo1.jpeg', lat: 53.430855, lng: -2.960833 },
    { id: 2, name: 'Paul Ince', team: 'Manchester United', photo: 'assets/imgs/photo2.jpeg', lat: 53.463097, lng: -2.291351 },
    { id: 3, name: 'Eric Cantona', team: 'Manchester United', photo: 'assets/imgs/photo3.jpeg', lat: 53.463097, lng: -2.291351 },
    { id: 4, name: 'Thierry Henry', team: 'Arsenal', photo: 'assets/imgs/photo4.jpeg', lat: 51.554902, lng: -0.108449 },
    { id: 5, name: 'Alan Shearer', team: 'Newcastle United', photo: 'assets/imgs/photo5.jpeg', lat: 54.975593, lng: -1.621678 },
    { id: 6, name: 'Dennis Bergkamp', team: 'Arsenal', photo: 'assets/imgs/photo6.jpeg', lat: 51.554902, lng: -0.108449 },
    { id: 7, name: 'Didier Drogba', team: 'Chelsea', photo: 'assets/imgs/photo7.jpeg', lat: 51.481683, lng: -0.190956 },
    { id: 8, name: 'Jurgen Klinsmann', team: 'Tottenham Hotspur', photo: 'assets/imgs/photo8.jpeg', lat: 51.604320, lng: -0.066395 },
    { id: 9, name: 'Robin Van Persie', team: 'Arsenal', photo: 'assets/imgs/photo9.jpeg', lat: 51.554902, lng: -0.108449 },
    { id: 10, name: 'David Beckham', team: 'Manchester United', photo: 'assets/imgs/photo10.jpeg', lat: 53.463097, lng: -2.291351 },
    { id: 11, name: 'Steven Gerrard', team: 'Liverpool', photo: 'assets/imgs/photo11.jpeg', lat: 53.430855, lng: -2.960833 },
    { id: 12, name: 'Ian Rush', team: 'Liverpool', photo: 'assets/imgs/photo12.jpeg', lat: 53.430855, lng: -2.960833 },
];

Next, open and edit src/app/tab1/tab1.page.ts then add these imports of Player array and Angular Router.

import { Router } from '@angular/router';
import { Player } from '../player';

Inject the Angular Router in the constructor params.

constructor(public router: Router) {}

Add the variables before the constructor to handle an array of objects and view type (list/grid).

persons = Player;
viewType = 'list';

Add these functions after the constructor to switch the view of the list or grid.

changeToGrid() {
  this.viewType = 'grid';
}

changeToList() {
  this.viewType = 'list';
}

Next, open and edit src/app/tab1/tab1.page.html then add these lines of HTML tags that display the list/grid from the array of objects.

<ion-header>
  <ion-toolbar>
    <ion-title>
      Player
    </ion-title>
    <ion-buttons slot="end">
      <ion-button *ngIf="viewType === 'grid'" (click)="changeToList()">
        <ion-icon slot="icon-only" name="list-box"></ion-icon>
      </ion-button>
      <ion-button *ngIf="viewType === 'list'" (click)="changeToGrid()">
        <ion-icon slot="icon-only" name="grid"></ion-icon>
      </ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list *ngIf="viewType === 'list'">
    <ion-list-header>
      Premier League Legend
    </ion-list-header>
    <ion-item *ngFor="let p of persons" [routerLink]="['/tabs/tab2/', p.id]">
      <ion-avatar slot="start">
        <img src="{{p.photo}}">
      </ion-avatar>
      <ion-label>
        <h2>{{p.name}}</h2>
        <h3>{{p.team}}</h3>
      </ion-label>
    </ion-item>
  </ion-list>

  <ion-grid *ngIf="viewType === 'grid'">
    <ion-row>
      <ion-col *ngFor="let p of persons" size-lg="3" size-md="4" size-sm="6" size="12">
        <ion-card>
          <img src="{{p.photo}}" />
          <ion-card-header>
            <ion-card-subtitle>{{p.name}}</ion-card-subtitle>
            <ion-card-title>{{p.team}}</ion-card-title>
          </ion-card-header>
        </ion-card>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-content>

As you can see, there are the buttons in the toolbar that show and hide based on the list/grid types. The click action will trigger the change of list/grid view types. So, there are 2 type of or which hide by "viewType" variable.

Don't forget to change the Tabs name in src/app/tabs/tabs.page.html to make tabs and its content is related.

<ion-tab-bar slot="bottom">
  <ion-tab-button tab="tab1">
    <ion-icon name="flash"></ion-icon>
    <ion-label>Player</ion-label>
  </ion-tab-button>

  <ion-tab-button tab="tab2">
    <ion-icon name="apps"></ion-icon>
    <ion-label>Details</ion-label>
  </ion-tab-button>

  <ion-tab-button tab="tab3">
    <ion-icon name="send"></ion-icon>
    <ion-label>Maps</ion-label>
  </ion-tab-button>
</ion-tab-bar>
Step #5. Display Data to the Ionic Card

We make two options to display details in Ionic Card in Tab 2. First, we will display a default static Ionic Card content if there's no data comes from other tabs. Second, we will display the Ionic Card of details that come from the other tabs. To do that, open and edit src/app/tab2/tab2.page.ts then add or modify these imports of Angular OnInit, ActivatedRoute, Router, and Player array.

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Player } from '../player';

Add implementation of Angular OnInit to the class name.

export class Tab2Page implements OnInit {
...
}

Inject the Angular ActivatedRoute and Router to the constructor.

constructor(public route: ActivatedRoute, public router: Router) {}

Add the variables before the constructor that hold details object and Player array.

details = { id: null, name: '', team: '', photo: '', lat: null, lng: null };
persons = Player;

Add an Angular ngOnInit function that finds an object from the player array.

ngOnInit() {
  if (this.route.snapshot.paramMap.get('id') !== 'null') {
    const id = parseInt(this.route.snapshot.paramMap.get('id'), 0);
    this.details = this.persons.find(x => x.id === id);
  }
}

We use ngOnInit because want to load the details from the array every tab 2 showed up. Next, add a function to navigate to the Tab 3 or show the Google Maps.

showMap(id: any) {
  this.router.navigate(['/tabs/tab3/', id]);
}

Next, open and edit src/app/tab2/tab2.page.html then replace all HTML tags with these.

<ion-header>
  <ion-toolbar>
    <ion-title>
      Details
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-card *ngIf="!details">
    <img src="assets/imgs/anfield.jpg" />
    <ion-card-header>
      <ion-card-subtitle>Anfield Stadium</ion-card-subtitle>
      <ion-card-title>Liverpool</ion-card-title>
    </ion-card-header>
    <ion-card-content>
      Anfield is a football stadium in Anfield, Liverpool, Merseyside, England, which has a seating capacity of 54,074, making it the seventh largest football stadium in England. It has been the home of Liverpool FC since their formation in 1892\. It was originally the home of Everton FC from 1884 to 1891, before they moved to Goodison Park after a dispute with the club president.
    </ion-card-content>
  </ion-card>

  <ion-card *ngIf="details">
    <img src="{{details.photo}}" />
    <ion-card-header>
      <ion-card-subtitle>{{details.name}}</ion-card-subtitle>
      <ion-card-title>{{details.team}}</ion-card-title>
    </ion-card-header>
    <ion-card-content>
      <ion-button (click)="showMap(details.id)">
        <ion-icon slot="icon-only" name="map"></ion-icon>
      </ion-button>
    </ion-card-content>
  </ion-card>
</ion-content>

As you see, there are two that display static details and details from objects based on details object's existence.

Step #6. Display Google Maps

In this step, we will show the Google Maps that come from the static latitude/longitude or dynamic latitude/longitude from the object. For that, open and edit src/app/tab3/tab3.page.ts then add or modify these imports of Ionic ViewChild, ElementRef, OnInit, Platform, ActivatedRoute, and Player object.

import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';
import { Platform } from '@ionic/angular';
import { ActivatedRoute } from '@angular/router';
import { Player } from '../player';

Declare the Google Map and map variable before the @Component.

declare var google;
let map: any;

Add the implementation of Angular OnInit in the class name line.

export class Tab3Page implements OnInit {
...
}

Inject the ActivatedRoute and Platform to the constructor.

constructor(public route: ActivatedRoute, public platform: Platform) {}

Add the variables of @ViewChild, details object, and Player array before the constructor.

@ViewChild('map', {static: false}) mapElement: ElementRef;
details = { id: null, name: '', team: '', photo: '', lat: null, lng: null };
persons = Player;

Add the Angular ngOnInit function that loads the Google Maps inside the Platform ready method.

ngOnInit() {
  if (this.route.snapshot.paramMap.get('id') === null) {
    this.platform.ready().then(() => {
      map = new google.maps.Map(this.mapElement.nativeElement, {
        center: { lat: -6.930560, lng: 107.558439 },
        zoom: 15
      });
    });
  } else {
    const id = parseInt(this.route.snapshot.paramMap.get('id'), 0);
    this.details = this.persons.find(x => x.id === id);
    this.platform.ready().then(() => {
      map = new google.maps.Map(this.mapElement.nativeElement, {
        center: { lat: this.details.lat, lng: this.details.lng },
        zoom: 15
      });
    });
  }
}

The Google Maps coordinate based on data that come from the previous Tab, if the data is null then we put the static coordinate. Next, open and edit src/app/tab3/tab3.page.html then replace all HTML tags with these.

<ion-header>
  <ion-toolbar>
    <ion-title>
      Show Google Maps
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <div #map id="map"></div>
</ion-content>

As you see, there's just a

that holds the Google Maps. To make this Google Maps working, we need to import or load the Google Maps Javascript API library to the src/index.html before the end of the tag.

<body>
  <app-root></app-root>
  <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBgZZK8umUqJn8d5CoIZqWPJ_qtMfqD9q0"></script>
</body>

The Google Maps only working if the

have a height. So, add these CSS codes to the src/app/tab3/tab3.page.scss.

#map {
    height: 690px;
}
Step #7. Run and Test the Ionic 4/Angular 8 Apps

In this step, we will be working with the Cordova before run and test the Ionic 4/Angular 8 apps to the Android and iOS devices. First, remove and add all platforms from this Ionic app project by typing these commands.

ionic cordova platform rm android
ionic cordova platform add android
ionic cordova platform rm ios
ionic cordova platform add ios

Now, you can run the Ionic 4/Angular 8 apps to the Android and iOS devices. Type this command to run directly to the Android device and make sure the Android device connected to your computer.

ionic cordova run android

For iOS, we need to build this app first.

ionic cordova build ios

Open the platforms/ios/MyApp.xcworkspace in your XCode application then run it to iOS device or Simulator. The app will look like this.




That it's, the Ionic 4 Tutorial: How to Create Mobile Apps Quickly. As usual, we always provide full working source codes from our GitHub.

Ionic build cannot find module error. How to import Android plugin?

I'm trying to develop an Android Plugin to use in an Ionic app.

I'm trying to develop an Android Plugin to use in an Ionic app.

I created the app with a starter project already provided by Ionic using ionic start myApp tabs.

I have also created, in a different folder, my plugin, that contains the following files.

plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    id="location-plugin" version="0.0.1">
<name>GSLocationManager</name>
<description>Location Plugin</description>
<license>MIT</license>
<keywords>cordova,device,sensors,location</keywords>

<js-module name="LocationManager" src="www/LocationManager.js">
<clobbers target="LocationManager" />
</js-module>

<engines>
<engine name="cordova" version=">=3.6.0"></engine>
</engines>

<platform name="android">
<preference name="GOOGLE_PLAY_SERVICES_VERSION" default="11+"/>
<preference name="ANDROID_SUPPORT_LIBRARY_VERSION" default="26+"/>
<preference name="ICON" default="@mipmap/icon" />
<preference name="SMALL_ICON" default="@mipmap/icon" />
<preference name="ACCOUNT_NAME" default="@string/app_name" />
<preference name="ACCOUNT_LABEL" default="@string/app_name" />
<preference name="ACCOUNT_TYPE" default="$PACKAGE_NAME.account" />
<preference name="CONTENT_AUTHORITY" default="$PACKAGE_NAME" />

<framework src="com.google.android.gms:play-services-location:$GOOGLE_PLAY_SERVICES_VERSION" />
<framework src="com.android.support:support-v4:$ANDROID_SUPPORT_LIBRARY_VERSION" />
<framework src="com.android.support:appcompat-v7:$ANDROID_SUPPORT_LIBRARY_VERSION" />
<!-- <framework src="android/dependencies.gradle" custom="true" type="gradleReference"/> -->

<source-file src="path/to/locationmanager/GSLocationManager.java"
target-dir="path/to/locationmanager"></source-file>

<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.hardware.location" />
</config-file>

<config-file target="res/xml/config.xml" parent="/*">
<feature name="GSLocationManager">
<param name="android-package" value="android.package.locationmanager.GSLocationManager" />
</feature>
</config-file>
</platform>

locationManager.js
var GSLocationManager = {
getCurrentLocation: function(success, failure) {
exec(success, failure, 'GSLocationManager', 'getCurrentLocation', []);
}
}

module.exports = GSLocationManager;

GSLocationManager.java
package android.package.locationmanager;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaPlugin;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import android.annotation.SuppressLint;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;

public class GSLocationManager extends CordovaPlugin {

private JSONObject data = new JSONObject();

// at the initialize function, we can configure the tools we want to use later, like the sensors
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
    super.initialize(cordova, webView);

}

// safety unregistering from the events if the application stops somehow
@Override
public void onDestroy() {

}

// this is the main part of the plugin, we have to handle all of the actions sent from the js
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
    if ("getCurrentLocation".equals(action)) {
        Location location = getCurrentLocation();
        JSONObject json = new JSONObject();
        json.put("latitude", location.getLatitude());
        json.put("longitude", location.getLongitude());
        callbackContext.success(json);
        return true;
    }
    return false;  // Returning false results in a "MethodNotFound" error.
}

@SuppressLint("MissingPermission")
private Location getCurrentLocation() {
    LocationManager locationManager = (LocationManager) cordova.getActivity().getApplicationContext().getSystemService(Context.LOCATION_SERVICE);

    Location lastKnownGPSLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    return lastKnownGPSLocation;
}

}

Then I created a package.json for my plugin usign plugman And after that, added my android plugin to my Ionic project by doing ionic cordova plugin add path/to/my/plugin

But I cannot seem to be able to import my plugin to app.module.ts using import { GSLocationManager } from 'globespinning-location-plugin' I try to build but CLI says ERROR in src/app/app.module.ts(12,31): error TS2307: Cannot find module 'globespinning-location-plugin'.

Any idea where the error is? How should I import a plugin created by me, and referenced from a local folder? I want to be able to call GSLocationManager.getCurrentLocation() inside my ionic app.