Using Hybrid Applications: The Example of the Pyjam Avatar Project
Ivan Khrunin, Pavel Malinovskiy
LiveNews – On behalf of the development team of the Avatar: WorldExplorer in Pyjam app, I would like to share our experience with using a hybrid application in practice.
Briefly about our hybrid program:
The Avatar: WorldExplorer in Pyjam program was initially created as a platform for fulfilling freelance orders. We studied the market and tried to collect all the tasks that could be performed remotely. This led us to an unusual idea that had not been seen before. Why not use the mobile phones that people around the world have at hand to travel the world? The concept is as follows: we wanted to create an application that would allow us to connect to anyone in the world who has our program installed. The person we connect to (a freelancer) receives compensation, and in return, they carry out navigational commands displayed on their phone screen. Essentially, the client connects to the freelancer and directs them on what to do using a joystick, much like in the game GTA. We came up with a new form of earning for freelancers that requires no particular skills – just a phone and internet access. Just imagine, you can travel to different corners of the planet! Wow!
In general, we set out to write an application, and we decided to develop a hybrid app because we wanted to do it quickly and with minimal financial costs.
What do we know about hybrid applications?
Hybrid apps are a type of mobile application that combines elements of both native and web applications. They are written using web technologies (such as HTML, CSS, and JavaScript) and are packaged as an app for a specific platform using container technologies, such as Apache Cordova (formerly PhoneGap) or Ionic’s Capacitor.
Key characteristics of hybrid applications:
- Development and Maintenance: Since hybrid apps use web technologies, developers can write the code once and run it on multiple platforms, which simplifies and reduces the cost of support and updates.
- Performance: Generally, hybrid apps perform slower than native apps because they rely on an embedded browser (WebView) to display content. However, modern devices and browser optimizations have significantly improved this situation, and the performance is quite acceptable for many types of applications.
- Access to Device Functionality: Hybrid apps can interact with device capabilities (camera, GPS, accelerometer, etc.) using various APIs and plugins.
- Distribution: Since hybrid apps are packaged for distribution through app stores (App Store, Google Play), they can take advantage of the same infrastructure and application discovery processes as native apps.
- Offline Functionality: Hybrid apps can provide offline functionality, storing data locally and synchronizing it once an internet connection is restored.
As examples of platforms and tools for creating hybrid applications, one can mention:
– Apache Cordova
Ionic Framework is an open-source set of user interface tools for building cross-platform mobile, web, and desktop applications using web technologies such as HTML, CSS, and JavaScript/TypeScript.
React Native (which is more of a hybrid approach but also allows the use of web technologies)
Xamarin (uses C# and .NET instead of traditional web technologies, but also represents an attempt to create a cross-platform application)
Flutter is an open-source cross-platform UI development technology from Google, introduced in 2017 and quickly gained popularity. It allows developers to create beautiful, natively compiled applications for mobile devices (iOS and Android), the web, and desktop (Windows, macOS, Linux) from a single codebase.
The choice between native and hybrid development will depend on many factors, including the required performance, the complexity of the needed device interactions, and the resources of the development team.
We chose the Ionic Framework, so I will share my experience and talk specifically about it.
Ionic is based on the concept of web components, which can be reused to create a user interface. When developing applications using Ionic, developers often use Angular to structure the application, although support for other popular frameworks such as React or Vue is also available.
First, let’s look at the basic structure of an Ionic application:
“`html
Home page
“`
“`typescript
// home.page.ts
import { Component } from ‘@angular/core’;
@Component({
selector: ‘app-home’,
templateUrl: ‘home.page.html’,
styleUrls: [‘home.page.scss’],
})
export class HomePage {
constructor() {}
sayHello() {
console.log(Hello, World!’);
}
}
“`
In this example, we see the basic HTML markup of Ionic with a header and a button, and the TypeScript file contains the logic for handling the button press event.
You can also add navigation between pages:
“`html
About App
Created by Pyjam Avatar.
“`
For navigation between pages, the Angular Router is used:
“`typescript
// app-routing.module.ts
import { NgModule } from ‘@angular/core’;
import { RouterModule, Routes } from ‘@angular/router’;
import { HomePage } from ‘./home/home.page’;
import { AboutPage } from ‘./about/about.page’;
const routes: Routes = [
{ path: ”, redirectTo: ‘home’, pathMatch: ‘full’ },
{ path: ‘home’, component: HomePage },
{ path: ‘about’, component: AboutPage }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
“`
To navigate between pages, add links to your markup:
“`html
…
…
“`
Let’s look at a few examples of using these plugins to access system functions in Ionic:
Using the native camera of the device with Capacitor:
“`typescript
import { Camera, CameraResultType } from ‘@capacitor/camera’;
async openCamera() {
const image = await Camera.getPhoto({
quality: 90,
allowEditing: true,
resultType: CameraResultType.Uri
});
console.log(image);
}
“`
Retrieving the current location of the user using the Capacitor Geolocation plugin:
“`typescript
import { Geolocation } from ‘@capacitor/geolocation’;
async getCurrentPosition() {
const coordinates = await Geolocation.getCurrentPosition();
console.log(‘current coordinates:’, coordinates);
}
“`
Reading and writing files using the Capacitor Filesystem plugin:
“`typescript
import { Filesystem, Directory } from ‘@capacitor/filesystem’;
async writeFile() {
await Filesystem.writeFile({
path: ‘secrets/text.txt’,
data: “This is data”,
directory: Directory.Documents,
encoding: FilesystemEncoding.UTF8
});
}
async readFile() {
const contents = await Filesystem.readFile({
path: ‘secrets/text.txt’,
directory: Directory.Documents,
encoding: FilesystemEncoding.UTF8
});
console.log(contents);
}
“`
Sending local notifications using the Capacitor Local Notifications plugin:
“`typescript
import { LocalNotifications } from ‘@capacitor/local-notifications’;
async scheduleNotification() {
const notif = await LocalNotifications.schedule({
notifications: [
{
title: “Notification title”,
body: “Notifications text”,
id: 1,
schedule: { at: new Date(Date.now() + 1000 * 5) },
sound: null,
attachments: null,
actionTypeId: “”,
extra: null
}
]
});
}
“`
Vibrating the device using the Capacitor or Cordova Vibration plugin:
“`typescript
import { Haptics, ImpactStyle } from ‘@capacitor/haptics’;
async vibrateDevice() {
await Haptics.impact({
style: ImpactStyle.Heavy
});
}
“`
A vast array of plugins for both Cordova and Capacitor extend the capabilities for integration with a wide range of native device functions such as Bluetooth, NFC, background tasks, contacts, calendar, and many others.
In each case, to work with native functions, you will need to add the corresponding plugin to the project, and then use the JavaScript interface provided by it to interact with these functions from the code of your Ionic application.