Akinon Release Notes (05/12/2025) are now live! Click here to learn what's new.
LogoLogo
API Reference
  • Home
  • Quick Start
  • Tutorials
  • Technical Guides
  • Release Notes
  • Glossary
  • Welcome to Akinon Technical Guides
  • ACC
    • ACC CLI
    • Create Application via CLI
    • Deploy Environment Variables
    • App Store for Developers
  • Omnitron
    • Product Types
    • Product Categorization
    • Splitting a Merged Order Item
  • Commerce
    • Shipping Rules Calculator
    • Data Source Shipping Options
    • Attribute Based Shipping Options
    • Filtering Products
    • Conversation & Messages
    • Sitemap Configuration
    • Weight-Based Product Sales
    • Group Attribute Sets
    • Contract Management
    • Find in Store for Whippy Ware
    • Plugins
    • Remote Price
    • E-mail Templates
    • Loyalty Accounts
    • Search Structure
    • User Segmentation & Rules
    • Promotions
  • OMS
    • Getting Started with OMS
    • Basic Setup
    • Scenarios
    • Capacity Feature
    • Package Management
      • Packages
      • Transfer
      • States
    • Commands
      • Packages
        • Package Command Parameters
        • DeAllocate Package Reservations Command
        • Channel Based Complete Packaging without Shipment Command
        • Complete Packaging with Shipment Command
        • Complete Packaging without Shipment Command
        • Package Refuse with Denial Reason Command
        • Product Not Found & Wrong Product Command
        • Product Not Found & Wrong Product Command Advanced
        • Package Packed for Refund Command
        • Block The Package For Action Command
        • Unblock the Package For Action Command
        • Update The Package’s Invoice
        • Manual Planning Command
      • Transfer
        • Transfer Order Advanced Command
        • Product for Transfer Not Found & Wrong Product Command
        • Transfer Delivered Command
        • Transfer Dispatch Command
        • Transfer Ready for Dispatch Command
        • Transfer Out Of Stock
      • Shipment
        • Shipment Order Command
        • Package Advanced Shipment Command
        • Ship The Package Command
        • Ship The Package without Shipment Integration Command
        • Update The Package’s Shipment Status Command
        • Update Shipment Info of Package Command
    • Inventory Locations & Engine
      • Properties & Domain Relation
      • Customization
      • Inventory Engine
    • Fulfillment
      • Shipments
      • Invoice Integration
    • Webhooks
      • Webhook Examples
        • Order Webhook
        • Package Webhook
        • Shipment Webhook
        • Stock Location Webhook
        • Transfer Webhook
    • Integrating OMS with Seller Center
  • Instore
    • Getting Started
    • Cash Register Integration
    • OTP (One Time Password) Process
    • Services
      • Password Reset Services
  • Marketplace Dashboard
    • N11 Marketplace Setup Configurations
    • Trendyol Marketplace Setup Configurations
    • Walmart Marketplace Setup Configurations
    • Amazon Marketplace Setup Configurations
    • Hepsiburada Marketplace Setup Configurations
  • Project Zero
    • Django
      • Basic Setup
      • Project Structure
        • Templates & Components
        • Private Dependencies
        • Omnife Project Submodule
        • Webpack
        • ESLint Rules
        • Bundles
        • Multilanguage & Translation
        • Environmental File
        • Custom Error Pages
        • Icon Font
      • Page Types
        • Static Pages & Flatpages
        • Account Page
          • Template Rendering in Account Pages
          • Forms & Validation
        • Basket Page
          • Redux Basket State
          • Basket Page - View
        • Checkout
          • Redux Checkout State
          • View & Template Rendering
          • Masking & Validation
      • Theming & Styling
      • Widgets
      • SEO Management
      • Extending Project Zero
    • Next.js
      • Basic Setup
      • Deployment
      • Static Assets
      • Plugins
      • Widgets
      • Icons
      • Localization
      • SEO Management
      • Advanced Usage
      • Data Fetching
        • Client
          • Account
          • Address
          • Basket
          • Checkout
          • Misc
          • Product
          • User
          • Wishlist
        • Server
          • Category
          • Flat Page
          • List
          • Menu
          • Product
          • SEO
          • Special Page
          • Widget
  • App Maker
    • Setup Your Environment
    • Plugin Quickstart
    • Create Project
    • Setup Existing Project
    • Deploy Project
    • Users and Roles
    • Add Public Key
    • App Maker CLI
    • Create App on Stores
      • Creating App on Apple App Store
      • Creating App on Google Play Store
    • Mobile App Framework
      • Configuration
      • Framework
      • Project Structure
        • Structure
        • Data Containers
        • Pages
      • Dependency Integration
        • Plugins
        • Akinon Plugin Adapter
  • Akifast
    • HPP
      • Getting Started
      • Authorization
      • Payment Session Creation
        • Key Points Before Creating a Payment Session
        • Creating Payment Session
        • Redirecting to the Payment Page
        • Errors Encountered During Payment Session Creation
      • Merchant Services
        • Shipping Query URL
        • Agreement Query URL
        • Other URLs
  • B2B
    • Getting Started
    • B2B Setup
  • Adds-on
    • Invoicer
      • Introduction
      • Invoice & Pay On Delivery Service
  • Channel App Template
    • Introduction
    • Installation and Usage
    • Development Steps
      • Folder Structure
      • Starting Step
      • Encoding the Sales Channel
        • Introduction
        • Setup
        • Products
        • Product Price
        • Product Stock
        • Product Image
        • Orders
        • Product Data
      • Adding a New Command to Akinon
      • Listening for External Requests
    • Architecture
      • Introduction
      • Integration
      • Services (Flows)
        • Introduction
        • Product Service
        • Price Service
        • Stock Service
        • Image Service
        • Order Service
  • Multi Regional Settings
    • Multi Regional Settings
Powered by GitBook

© 2025 Akinon. All rights reserved.

On this page
  • Creating a Plugin
  • Using Plugin in Project
  • Developing a Plugin
  • Example React Native Camera
  • Example Firebase

Was this helpful?

  1. App Maker
  2. Mobile App Framework
  3. Dependency Integration

Plugins

PreviousDependency IntegrationNextAkinon Plugin Adapter

Last updated 16 days ago

Was this helpful?

App Maker creates a mobile development environment with some dependencies that have proven stable. You may wish to add required modules or third-party services (Analytics, push notification, recommendations, etc.) to this environment. This is where plugins come into play. They allow you to add the modules you need to the environment and write integrations.

When installing native modules to the Environment, some modules are installed automatically. Some require more complex setup processes. For example, a module may require you to add some permissions to AndroidManifest.xml and Info.plist files during installation, or even to add a code block to your application's native files. In order to make complex installations like this, you need to write scripts where you can edit native files.

Plugins have two stages: installation and integration. During the installation stage, required actions are taken for the installation process. The integration phase includes the integration required for the installed module to work with the application's javascript. To develop a plugin with a template that includes these steps, continue reading the next section “Creating a plugin”.

Creating a Plugin

In order to install the environment in which you will develop the plugin, you need to run the following command in the main directory of the project.

appmaker plugin create

Plugin names should be unique and adhere to the formatting akinon-react-native-camera.

Plugin Structure

After running the command appmaker plugin create, a plugin will be created, with the name you specified, in the .plugins directory in your project's main directory. This plugin should look like this.

Installation

In this directory, index.js exports the installation scripts and the npm dependencies that need to be installed as objects.

There should be installation scripts specific to these platforms in the android and ios directories.

android&ios / install.js should contain the installation processes needed by the npm package to be installed. For instance, when you wish to install the package , you should write scripts that will add the necessary permissions for android to AndroidManifest.xml.

The scripts written in the file android&ios / post-install.js run after the npm package is installed in the project. For instance, if you need to do something about the package installed in the ios/Pods directory, it should be done in this file.

You can run these scripts with the command appmaker plugin run ios.

Integration

In this directory, index.js should export a class. If this class has a function called init, this function will be run automatically at the start of the application. You can use the init function to subscribe to Framework services (Analytics, Deeplink).

akinon.plugin.js

This exports installation scripts.

config.json

The plugin may have client-specific configs (API_KEY, CLIENT_ID, etc). Such configs are defined in this file.

Using Plugin in Project

A plugin created with the command appmaker plugin create is automatically set up to be used in your project. The plugin you created in Akinon.json > plugins config should look like this.

{
  "plugins": {
    "akinon-react-native-camera": {
      "name": "akinon-react-native-camera",
      "moduleName": "AkinonReactNativeCamera",
      "config": {}
    }
  }
}

name (string)

The name of the plugin is specified in this field. The value written in this field and the folder name of the plugin must be identical.

moduleName (string)

When you wish to use the plugin in a project, the name you need to import is specified in this field.

import Plugins from '_dependencies/plugins';
const { AkinonReactNativeCamera } = Plugins;

config (object)

This field is used to specify the project-specific configs required by the plugin.

Developing a Plugin

When you create the plugin with the command appmaker plugin create, the plugin is ready for development.

When developing the installation scripts of the plugin, you need to edit the files in the project using the Modifiers services. These modifiers may be inaccurate or incomplete during development. It would be costly to restore project files after configuring them incorrectly or incompletely. To avoid this, it is recommended to run the appmaker's command plugin preview while developing installation scripts.

appmaker plugin preview android

You need to add the —post-install parameter to run the post-install scripts of the plugin.

This command shows the changes to be made by the installation scripts you have developed to the project files. It does not edit project files.

After making sure that the installation scripts are working correctly, you can now edit project files. In order to do this, you have to run the command plugin run.

appmaker plugin run android

This command writes the changes seem in the preview command to project files, and the project is ready to be built.

You may wish to develop a plugin without using the command appmaker plugin create. For instance, you may wish to include a plugin written for a different project. You need to clone the plugin you wish to include to the .plugins directory in the main directory of the project and run the command plugin add.

appmaker plugin add name

This command will edit akinon.json for you, enabling you to use the plugin in your project.

You may also wish to develop the plugin you use in a project. When you install a project with the command appmaker project install, the project is set up ready for build. However, you do not wish the plugin you will develop to be installed in the project. In this case, after installing the project, the plugin you wish to develop is cloned to the .plugins directory and this command is run in the project directory.

appmaker project install --exclude-plugins

This command will re-configure the project without the plugin that is cloned under .plugins and defined in the plugins config in akinon.json and will install it ready for build.

After the development is finished, you can run the command plugin run.

appmaker plugin run android

Third Parties

Third-party plugins are a bit more complex than installing other react native plugins. You may also need to use features such as Analytics, and DeepLink for third-party plugins. For such features, Analytics and DeepLink services are available in the framework. You can complete the integration using these services. Check out Example Firebase for a sample case.

Modifiers

Modifying Xcode

You need to use XcodeModifier to edit the project with Xcode. See this document for detailed information.

const { Modifiers, Paths } = require('akinon-plugin-adapter');
const { XcodeModifier } = Modifiers;

class Install {
  async modifyXcode() {
    const { getPBXProjectPaths } = Paths.ios;
    const xcode = new XcodeModifier(getPBXProjectPaths());
    xcode.parse();
    xcode.updateBuildSettings('IPHONEOS_DEPLOYMENT_TARGET', '12.0', "akinon");
    return xcode.writeAsync();
  }
  
  async start() {
    await this.modifyXcode();
  }
}

You can try the following steps to make it easier to write scripts for Xcode.

  • Open a project with Xcode.

  • Make the related changes with Xcode and run the command appmaker project diff ios. This command will show the Xcode changes. You can write scripts based on these changes.

  • Run the command appmaker project reset ios to undo Xcode changes. This command will reset the ios changes.

Modifying Info.plist

You need to use PlistModifier to edit the Info.plist files. See this document for detailed information.

const { Modifiers, Paths } = require('akinon-plugin-adapter');
const { PlistModifier } = Modifiers;

class Install {
  async modifyPlist() {
    const { getInfoPlist } = Paths.ios;
    const infoPlist = new PlistModifier(getInfoPlist()); 
    const parsedPlist = await infoPlist.readAsync();
    parsedPlist["NSCameraUsageDescription"] = "This app requires access to the camera."
    return infoPlist.writeAsync(parsedPlist);
  }
  
  async start() {
    await this.modifyPlist();
  }
}

Modifying Podfile

You need to use PodModifier to edit the Podfile file. See this document for detailed information.

const { Modifiers, Paths } = require('akinon-plugin-adapter');
const { PodModifier } = Modifiers;

class Install {

  async modifyPodfile() {
    const { getPodFile } = Paths.ios;
    const podFile = new PodModifier(getPodfile());
    podFile.addToTarget("akinon", "Pod 'Yoga' ");
    return podFile.writeAsync();
  }

  async start() {
    await this.modifyPodfile();
  }
}

Modifying AppDelegate

You need to use AppDelegateModifier to edit the AppDelegate.h and AppDelegate.m files. See this document for detailed information.

const { Modifiers, Paths } = require('akinon-plugin-adapter');
const { AppDelegateModifier } = Modifiers;

class Install {

  async modifyAppDelegate() {
    const { getAppDelegate } = Paths.ios;
    const appDelegate = new AppDelegateModifier(getAppDelegate());
    appDelegate.addImports(['#import "AppDelegate.h"']);
    return appDelegate.writeAsync();
  }

  async start() {
    await this.modifyAppDelegate();
  }
}

Modifying AndroidManifest.xml

You need to use XMLModifier to edit AndroidManifest and other xml files. See this document for detailed information.

const { Modifiers, Paths } = require('akinon-plugin-adapter');
const { XMLModifier } = Modifiers;

class Install {

  async modifyManifest() {
    const { getManifest } = Paths.android;
    const manifest = new XMLModifier(getManifest());
    const xml = await manifest.parseAsync();
    xml.manifest['uses-permission'].push({
      $: { 
        'android:name': "android.permission.ACCESS_FINE_LOCATION"
      }
    })
    return manifest.writeAsync(xml);
  }

  async start() {
    await this.modifyManifest();
  }
}

Modifying Gradle

You need to use GradleModifier to edit the Build.gradle file. See this document for detailed information.

const { Modifiers, Paths } = require('akinon-plugin-adapter');
const { GradleModifier } = Modifiers;

class Install {

  async modifyGradle() {
    const { getBuildGradle } = Paths.android;
    const gradle = new GradleModifier(getBuildGradle());
    gradle.addDependencies(` maven {url 'http://developer.huawei.com/repo/'}`);
    return gradle.writeAsync();
  }

  async start() {
    await this.modifyGradle();
  }
}

Modifying MainApplication.java

You need to use JavaModifier to edit the MainApplication.java file. See this document for detailed information.

const { Modifiers, Paths } = require('akinon-plugin-adapter');
const { JavaModifier } = Modifiers;

class Install {

  async modifyMainApplication() {
    const { getMainApplication } = Paths.android;
    const mainApplication = new JavaModifier(getMainApplication());
    mainApplication.addImports("java.util.List", "java.util.Arrays");
    return mainApplication.writeAsync();
  }

  async start() {
    await this.modifyMainApplication();
  }
}

Modifying Other Files

You have to use FileModifier to change different file types. You can also use the features of this modifier in other defined Modifier services. Occasionally, the modifier you use may not fully meet your needs. In such cases, you can use custom Regex patterns with FileModifier methods.

As an example, you can refer to AppDelegateModifier's applyPatch method below.

const { Modifiers, Paths } = require('akinon-plugin-adapter');
const { AppDelegateModifier } = Modifiers;

class Install {

  async modifyAppDelegateHeader() {
    const { getAppDelegate } = Paths.ios;
    const appDelegate = new AppDelegateModifier(getAppDelegateHeader());
    appDelegate.addImports(['#import UserNotifications/UNUserNotificationCenter.h']);
    appDelegate.applyPatch({
      pattern: /(@interface AppDelegate(.*))+(?=>)/,
      patch: ', UNUserNotificationCenterDelegate'
    });
    return appDelegate.writeAsync();
  }

  async start() {
    await this.modifyAppDelegateHeader();
  }
}

Regex patterns may no be compatible with the plugins you’ve developed or the changes incoming with the new environment version.

Example React Native Camera

Let's assume we are developing a plugin for the react-native-camera dependency.

Installation

During installation, setup processes for third-party libraries are completed. This includes adding dependencies to package.json and modifying native files.

1. Create Plugin

Run the following command to create a new plugin:

→ app-maker plugin create

You will be prompted to provide a name for the plugin. Enter the plugin name:

→ akinon-react-native-vision-camera

This command will generate a plugin under the directory: .plugins/akinon-react-native-vision-camera.

2. Install npm Package

npm packages should be added to the project's package.json file. To do this, define the names and versions of the required npm packages in the specified directory.

// .plugins/akinon-react-native-vision-camera/installation/index.js
module.exports = {
  dependencies: {
    "react-native-vision-camera": "2.15.4",
  },
  ...
};

3. Android Installation

Add the required permissions (android.permission.CAMERA and android.permission.RECORD_AUDIO) to the android/app/src/main/AndroidManifest.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<manifest 
  xmlns:android="http://schemas.android.com/apk/res/android" 
  xmlns:tools="http://schemas.android.com/tools" 
  package="com.akinon.shop"
  android:versionCode="1" android:versionName="1.0.0">
  
// other permissions
  <uses-permission android:name="android.permission.CAMERA" />  // Add me --- /\
  <!-- optionally, if you want to record audio: --> 
  <uses-permission android:name="android.permission.RECORD_AUDIO" />  // Add me --- /\
</manifest>

Automate this modification with the following script:

// .plugins/akinon-react-native-vision-camera/installation/android/install.js
const { Paths, Modifiers } = require('akinon-plugin-adapter');
const { XMLModifier } = Modifiers;

class Install {
  constructor(plugin) {}

  addPermissions(xml, permissions) {
    permissions.forEach((permission) =>
      xml.manifest['uses-permission'].push({ $: { 'android:name': permission } })
    );
  }

  async modifyAndroidManifest() {
    const mod = new XMLModifier(Paths.android.getManifest());
    let xml = await mod.parseAsync();
    this.addPermissions(xml, [
      'android.permission.CAMERA',
      'android.permission.RECORD_AUDIO'
    ]);
    return mod.writeAsync(xml);
  }

  async start() {
    await this.modifyAndroidManifest();
  }
}

exports.default = Install;

4. iOS Installation

Add the permissions (NSCameraUsageDescription and NSMicrophoneUsageDescription) to ios/akinon/Info.plist:

// ios/akinon/Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    // ...
    // Add me --- \/
    <key>NSCameraUsageDescription</key> 
    <string>$(PRODUCT_NAME) needs access to your Camera.</string> 
    
    <!-- optionally, if you want to record audio: -->
    <key>NSMicrophoneUsageDescription</key> 
    <string>$(PRODUCT_NAME) needs access to your Microphone.</string> 
    // Add me --- /\
  </dict>
</plist>

Automate this modification with the following script:

// .plugins/akinon-react-native-vision-camera/installation/ios/install.js
const { Paths, Modifiers } = require('akinon-plugin-adapter');
const { PlistModifier } = Modifiers;

class Install {
  constructor(plugin) {}

  async modifyInfoPlist() {
    const mod = new PlistModifier(Paths.ios.getInfoPlist());
    const plist = await mod.readAsync();
    plist.NSCameraUsageDescription = '$(PRODUCT_NAME) needs access to your Camera.';
    plist.NSMicrophoneUsageDescription = '$(PRODUCT_NAME) needs access to your Microphone.';
    return mod.writeAsync(plist);
  }

  async start() {
    await this.modifyInfoPlist();
  }
}

exports.default = Install;

Preview and Run Installation

Preview installation scripts without making changes to files:

app-maker plugin preview ios && app-maker plugin preview android

Run the installation scripts:

app-maker plugin run ios && app-maker plugin run android

Integration

After completing the installation phase, you need to write a JavaScript integration to utilize third-party libraries in your application.

Camera Component

The Camera component you want to use in the application should be developed in the integration layer.

First, create the index.js file under .plugins/akinon-react-native-vision-camera/integration/camera to utilize the react-native-vision-camera dependency:

//`.plugins/akinon-react-native-vision-camera/integration/camera/index.js`
import { Camera as NativeCamera, useCameraDevices } from 'react-native-vision-camera';
import { ReactNative, React } from '_dependencies';

const { StyleSheet, TouchableOpacity, Text } = ReactNative;
const { useEffect, useState } = React;

const Camera = () => {
  const devices = useCameraDevices();
  const [permissions, setPermissions] = useState({
    camera: "denied",
    microphone: "denied",
  });

  const requestPermissions = async () => {
    const newCameraPermission = await NativeCamera.requestCameraPermission();
    const newMicrophonePermission = await NativeCamera.requestMicrophonePermission();
    setPermissions({
      camera: newCameraPermission,
      microphone: newMicrophonePermission,
    });
  };

  const checkPermissions = async () => {
    const cameraPermission = await NativeCamera.getCameraPermissionStatus();
    const microphonePermission = await NativeCamera.getMicrophonePermissionStatus();
    setPermissions({
      camera: cameraPermission,
      microphone: microphonePermission,
    });
  };

  useEffect(() => {
    checkPermissions();
  }, []);

  const device = devices.back;
  if (device == null) return <Text>Loading</Text>;
  if (permissions.camera === 'denied')
    return (
      <TouchableOpacity onPress={requestPermissions}>
        <Text>Request Permissions</Text>
      </TouchableOpacity>
    );
  return <NativeCamera isActive={true} style={StyleSheet.absoluteFill} device={device} />;
};

export default Camera;

Export and Use the Component:

To use the component you created within the src layer, you need to export it in the .plugins/akinon-react-native-vision-camera/integration/index.js file.

import Camera from './camera';

export default {
  Camera
};

You can use the Camera component you created in the src layer at the desired location, as shown in the example below:

import { React, AsyncStorage, RnSafeAreaContext } from '_dependencies';
import { Container } from '@elements';
import Plugins from '_dependencies/plugins.js'; // Add me --- /\

const {Camera} =  Plugins.AkinonReactNativeVisionCamera;  // Add me --- /\

const HomePage = ({}) => {
  return (
    <Container className="homePage.gridElements.container" excludeEdges={['top']}>
      <Camera /> // Add me --- /\
    </Container>
  );
};

export default HomePage;

Example Firebase

Let’s say we ‘re developing a plugin for Firebase.

Installation

During the installation phase, the setup processes of the third party are completed. These processes include, among others, adding dependency to package.json and modifying native files.

  1. Create Plugin

appmaker plugin create

Plugin name will be asked after running this command. Name of the plugin should be entered.

akinon-react-native-firebase

Running this command will create a plugin in the project’s .plugins/akinon-react-native-firebase directory.

  1. Install npm Package

  • @react-native-firebase/app

  • @react-native-firebase/analytics

  • @react-native-firebase/messaging

The npm packages must be added to the project's package.json file. In order to do this, the name and versions of npm packages are defined in the specified directory.

// .plugins/akinon-react-native-firebase/installation/index.js
module.exports = {
  dependencies: {
    "@react-native-firebase/app": "14.11.1",
    "@react-native-firebase/analytics": "14.11.1",
    "@react-native-firebase/messaging": "14.11.1"
  },
  ...
};
  1. Android Installation

You need to download google-services.json file from Firebase console and place it in /android/app/google-services.json directory.

In Akinon.json, you can write the path of the google-service file in the plugin config. (You can also write to a field other than Akinon.json.)

// akinon.json
{
  "plugins": {
    "akinon-react-native-firebase": {
      ...,
      "config": {
        "android": {
          "googleServiceFile": "./src/assets/resources/google-services.json"
        }
      }
    }
  }
}

Using the config in Akinon.json, you can write the script to move the google-services.json file to the android/app directory.

// .plugins/akinon-react-native-firebase/installation/android/install.js
const { Modifiers, Paths } = require("akinon-plugin-adapter");
const { FileModifier } = Modifiers;

class Install {
  constructor(plugin) {
    this.config = plugin.config
  }

  async copyGoogleServiceFile() {
    const file = new FileModifier();
    const {
      android: { googleServiceFile }
    } = this.config;

    return file.copyFile(
      Paths.project.getPath(googleServiceFile),
      `${Paths.android.getAndroidFolder().path}/app/google-services.json`
    );
  }

  async start() {
    await this.copyGoogleServiceFile();
  }
}

exports.default = Install;

While developing plugins, the akinon-plugin-adapters package simplifies the process with services such as Modifiers, Paths. See this document for more detailed information about these services.

In the file android/build.gradle, you need to add classpath 'com.google.gms:google-services:4.3.13' service as dependency under buildscript.

// android/build.gradle
buildscript {
  dependencies {
    // ... other dependencies
    classpath 'com.google.gms:google-services:4.3.13' // Add me --- /\
  }
}

For this:

// .plugins/akinon-react-native-firebase/installation/android/install.js
const { Modifiers, Paths } = require("akinon-plugin-adapter");
const { FileModifier, GradleModifier } = Modifiers;

class Install {
  constructor(plugin) {
    this.config = plugin.config
  }

  async copyGoogleServiceFile() {
    ...
  }

  async modifyBuildGradle() {
    const { getBuildGradle } = Paths.android
    const gradle = new GradleModifier(getBuildGradle());
    const dependencies = `classpath 'com.google.gms:google-services:4.3.13'`;
    gradle.addDependencies(dependencies);
    return gradle.writeAsync();
  }

  async start() {
    await this.copyGoogleServiceFile();
    await this.modifyBuildGradle();
  }
}

exports.default = Install;

To the file android/app/build.gradle, you need to add the code apply plugin: 'com.google.gms.google-services' that will enable you to use Google services.

// android/app/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services' // - Add this line

For this:

// .plugins/akinon-react-native-firebase/installation/android/install.js
const { Modifiers, Paths } = require("akinon-plugin-adapter");
const { FileModifier, GradleModifier } = Modifiers;

class Install {
  constructor(plugin) {
    this.config = plugin.config
  }

  async copyGoogleServiceFile() {
    ...
  }

  async modifyBuildGradle() {
    ...
  }

  async modifyAppBuildGradle() {
    const { getAppBuildGradle } = Paths.android;
    const gradle = new GradleModifier(getAppBuildGradle());
    const applies = `apply plugin: 'com.google.gms.google-services'`;
    gradle.addApply(applies);
    return gradle.writeAsync();
  }

  async start() {
    await this.copyGoogleServiceFile();
    await this.modifyBuildGradle();
    await this.modifyAppBuildGradle();
  }
}

exports.default = Install;

We need to add code to update the value of the com.google.firebase.messaging.default_notification_color meta data in the android/app/src/main/AndroidManifest.xml file.

// android/app/src/main/AndroidManifest.xml
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/iconBackground" /> // Modify android:resource

For this:

// .plugins/akinon-react-native-firebase/installation/android/install.js
const { Modifiers, Paths } = require("akinon-plugin-adapter");
const { FileModifier, GradleModifier, XMLModifier } = Modifiers;

class Install {
  constructor(plugin) {
    this.config = plugin.config
  }

  async copyGoogleServiceFile() {
    ...
  }

  async modifyBuildGradle() {
    ...
  }

  async modifyAppBuildGradle() {
    ...
  }
  
  async modifyManifest() {
    const { getManifest } = Paths.android;
    const manifest = new XMLModifier(getManifest());
    const parsedManifest = await manifest.parseAsync();
    const newMetaData = parsedManifest.manifest.application[0]["meta-data"].map((metaData) => {
      if (metaData.$["android:name"] === "com.google.firebase.messaging.default_notification_color") {
        metaData.$["android:resource"] = "@color/white";
      };
      return metaData;
    });
    parsedManifest.manifest.application[0]["meta-data"] = newMetaData;
    return manifest.writeAsync(parsedManifest);
  };

  async start() {
    await this.copyGoogleServiceFile();
    await this.modifyBuildGradle();
    await this.modifyAppBuildGradle();
    await this.modifyManifest();
  }
}

exports.default = Install;
  1. iOS Installation

You need to download GoogleService-Info.plist from Firebase console and put it in /ios/akinon/ directory

In Akinon.json, you can write the path of the google-service file in the plugin config.

// akinon.json
{
  "plugins": {
    "akinon-react-native-firebase": {
      ...,
      "config": {
        "ios": {
          "googleServiceFile": "./src/assets/resources/GoogleService-Info.plist"
        }
      }
    }
  }
}

You can write the script that will move the GoogleService-Info.plist file to the ios/akinon directory by using the config in Akinon.json; however, this will not be enough. When you add a file to the project or change a config with Xcode, changes are made by xcode in the ios/akinon.xcodeproj/project.pbxproj file. You have to make these changes with scripts.

// .plugins/akinon-react-native-firebase/installation/ios/install.js
const { Modifiers, Paths } = require("akinon-plugin-adapter");
const { XcodeModifier } = Modifiers;

class Install {
  constructor(plugin) {
    this.config = plugin.config
  }

  async copyGoogleServiceFile() {
    const {
      ios: { googleServiceFile }
    } = this.config;
    const { getPBXProjectPaths } = Paths.ios;
    const xcode = new XcodeModifier(getPBXProjectPaths());
    xcode.parse();
    xcode.createFile({
      sourcePath: Paths.project.getPath(googleServiceFile),
      destinationPath: Paths.ios.getIosFolder().path + "/akinon",
      name: "GoogleService-Info.plist",
      pbxFilePath: "akinon/GoogleService-Info.plist"
    }, "akinon");
    return xcode.writeAsync();
  }

  async start() {
    await this.copyGoogleServiceFile();
  }
}

exports.default = Install;

After adding the GoogleService-Info.plist file, you need to edit the AppDelegate.m file and initialize Firebase. The code block you want to add is as follows:

// ios/akinon/AppDelegte.mm
#import Firebase.h // Add me
...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add me --- \/
if ([FIRApp defaultApp] == nil) {
  [FIRApp configure];
}
// Add me --- /\
...
}

In order to make these changes in the AppDelegate.m file, you need to write a script as shown below.

// .plugins/akinon-react-native-firebase/installation/ios/install.js
const { Modifiers, Paths } = require("akinon-plugin-adapter");
const { XcodeModifier, AppDelegateModifier } = Modifiers;

class Install {
  constructor(plugin) {
    this.config = plugin.config
  }

  async copyGoogleServiceFile() {
   ...
  }

  async modifyAppDelegate() {
    const { getAppDelegate } = Paths.ios;
    const appDelegate = new AppDelegateModifier(getAppDelegate());
    const patch = ` 
    if ([FIRApp defaultApp] == nil) {
      [FIRApp configure];
    }`
    const imports = ['#import <Firebase.h>'];
    appDelegate.addImports(imports);
    appDelegate.applyPatch({
      pattern: /didFinishLaunchingWithOptions:.*([\n]{)/gm,
      patch
    });
    return appDelegate.writeAsync();
  }

  async start() {
    await this.copyGoogleServiceFile();
    await this.modifyAppDelegate();
  }
}

exports.default = Install;

You need to edit the Info.plist file and specify the services that will run in the background. The code block you want to add is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    ...
    // Add me --- \/
    <key>UIBackgroundModes</key> 
    <array>
      <string>fetch</string>
      <string>remote-notification</string>
    </array>
    // Add me --- /\
  </dict>
</plist>

To make these changes in the Info.plist file, you need to write a script as shown below.

// .plugins/akinon-react-native-firebase/installation/ios/install.js
const { Modifiers, Paths } = require("akinon-plugin-adapter");
const { XcodeModifier, AppDelegateModifier, PlistModifier } = Modifiers;

class Install {
  constructor(plugin) {
    this.config = plugin.config
  }

  async copyGoogleServiceFile() {
   ...
  }

  async modifyAppDelegate() {
    ...
  }
  
  async modifyPlist() {
    const { getInfoPlist } = Paths.ios;
    const mod = new PlistModifier(getInfoPlist());
    const plist = await mod.readAsync();
    plist['UIBackgroundModes'] = ["fetch", "remote-notification"];
    return mod.writeAsync(plist);
  }
  
  async start() {
    await this.copyGoogleServiceFile();
    await this.modifyAppDelegate();
    await this.modifyPlist();
  }
}

exports.default = Install;

After editing the Info.plist, you need to edit the akinon.entitlements file and configure the environment for Push notifications. The code block you want to add is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    ...
    // Add me --- \/
    <key>aps-environment</key>
    <string>development</string>
    // Add me --- /\
  </dict>
</plist>

To make these changes in the akinon.entitlements file, you need to write a script as shown below.

// .plugins/akinon-react-native-firebase/installation/ios/install.js
const { Modifiers, Paths } = require("akinon-plugin-adapter");
const { XcodeModifier, AppDelegateModifier, PlistModifier } = Modifiers;

class Install {
  constructor(plugin) {
    this.config = plugin.config
  }

  async copyGoogleServiceFile() {
   ...
  }

  async modifyAppDelegate() {
    ...
  }

 async modifyPlist() {
   ...
  }
  
  async modifyEntitlements() {
    const { getEntitlements } = Paths.ios;
    const mod = new PlistModifier(getEntitlements());
    const plist = await mod.readAsync();
    plist['aps-environment'] = 'development';
    return mod.writeAsync(plist);
  }

  async start() {
    await this.copyGoogleServiceFile();
    await this.modifyAppDelegate();
    await this.modifyPlist();
    await this.modifyEntitlements();
  }
}

exports.default = Install;

In order to run the installation scripts:

appmaker plugin run ios && appmaker plugin run android

This command is run in the project directory and Firebase installation is completed.

Integration

After the installation phase is finalized, you need to write javascript integration to use the third party in the application.

Analytics

Let’s say we’re writing this integration for Firebase Analytics.

Subscribe your analytics integration to Framework’s AnalyticsService.

// .plugins/akinon-react-native-firebase/integration/index.js
import AnalyticsService from '@services/analytics/service';

import Analytics from "./analytics";

class Firebase {
  init() {
    AnalyticsService.subscribe("FirebaseAnalytics", new Analytics());
  }
}

export default new Firebase();

The init function runs before the application is rendered. This function is useful in cases such as subscribe operations and third party sdk initialize.

Initially, the init function of the integration runs when the Analytics service is ready. This function enables analytics-specific initialization operations. The remove function works when the Analytics service is unmounted from the application.

// .plugins/akinon-react-native-firebase/integration/analytics/index.js

class Analytics {
  init() {
   
  }

  remove() {

  }
}

export default Analytics;

If you wish to send an event to firebase when you view a product:

 // .plugins/akinon-react-native-firebase/integration/analytics/index.js
import analytics from '@react-native-firebase/analytics';

class Analytics {
  ...
  static async productImpression(nextState, prevState, payload) {
    const { productDetail = {}} = nextState;
    const { product = {}} = productDetail;
    const item = {
      item_id: product.sku,
      item_name: product.name,
      item_category: product.attributes.category,
      item_variant: product.attributes.color,
      item_brand: product.brand,
      price: product.price
    }

    await analytics().logEvent("view_item", item);
  }
}

export default Analytics;

When the Product Detail page is opened, the integrated productImpression function will run automatically. You can find all the data about the product in the nextState parameter. Click to access Analytics functions.

Deep Link

Subscribe your deeplink integration to Framework’s DeepLinkService.

// .plugins/akinon-react-native-firebase/integration/index.js
import DeepLinkService from '@services/deepLink';

import DeepLink from "./deepLink";

class Firebase {
  init() {
    AnalyticsService.subscribe("FirebaseAnalytics", new Analytics());
    DeepLinkService.subscribe("FirebaseNotification", new DeepLink());
  }
}

export default new Firebase();

Initially, the init function of the integration runs when the DeepLink service is ready. This function enables deeplink-specific initialization operations. The remove function works when the DeepLink service is unmounted from the application.

// .plugins/akinon-react-native-firebase/integration/deepLink/index.js

class DeepLink {
  init() {
   
  }

  remove() {

  }
}

export default DeepLink;

Let's say we’re sending a push notification to the application using Firebase messaging. With push notification, you may wish to direct users to pages such as product list and product detail. In order to do this, you can access the push notification payload by using Firebase messaging's listeners in the init function. Through the publishNotificationOpen method of DeepLinkService, you can redirect to the relevant page when the notification is opened.

// .plugins/akinon-react-native-firebase/integration/deepLink/index.js
import messaging from '@react-native-firebase/messaging';
import DeepLinkService from '@services/deepLink';

class DeepLink {
  init() {
   messaging().onMessage(async notificationPayload => {
      DeepLinkService.publishNotificationOpen({
        url: notificationPayload.data.url,
        foreground: false
      });
    });
  }
}

export default DeepLink;

Analytics Events

When you create a method with the following events for the analytics service you have developed, the created method will be triggered when the action type associated with the event is ignited.

User

Action Type
Event Name

FETCH_CURRENT_USER_FULFILLED_FOR_LOGIN

userLogin

CLEAR_AUTH_STATE

userLogout

FETCH_CURRENT_USER_FULFILLED_FOR_INDEX

currentUser

Basket

Action Type
Event Name

FETCH_BASKET_FULFILLED

basketImpression

FETCH_BASKET_FULFILLED_TO_UPDATE

cartChanges

FETCH_BASKET_DISCOUNT

couponUsed

BASKET_ADD_TO_FAVOURITE_FULFILLED

addToFavOnBasket

ADDED_TO_CART_FULFILLED

addedToCart

Orders

Action Type
Event Name

CANCELLATION_REQUEST

cancelOrder

Product Detail

Action Type
Event Name

PD_ADD_TO_FAVOURITE_FULFILLED

addToFavOnPd

PD_REMOVE_FROM_FAVOURITE_FULFILLED

removeFromFavOnPd

FETCH_PRODUCT_DETAIL_FULFILLED

productImpression

Product List

Action Type
Event Name

PL_ADD_TO_FAVOURITE_FULFILLED

addToFavOnPd

FETCH_PRODUCT_LIST_FULFILLED

productsImpressions

PL_REMOVE_FROM_FAVOURITE_FULFILLED

removeFromFavOnPl

SET_SORTER

setSorter

Register

Action Type
Event Name

REGISTER_COMPLETED

userRegister

Search

Action Type
Event Name

FETCH_SEARCH_FULFILLED

searched

Checkout Success

Action Type
Event Name

WEB_CHECKOUT_OPENED

checkoutImpression

FETCH_CHECKOUT_COMPLETED_SUCCESS

measuringPurchases, measuringFirstPurchase, addShippingInfo, addPaymentInfo

FIRST_PURCHASE_ORDERED

firstPurchaseOrdered

The akinon-plugin-adapters package simplifies the process with services like Modifiers and Paths. Refer to the for more details.

Getting Started | VisionCamera
React Native Vision Camera
documentation
React Native Firebase
Analytics | React Native Firebase