diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..65365be
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+[*]
+
+indent_style = space
+indent_size = 2
+
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..030ef14
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+*.pbxproj -text
+# specific for windows script files
+*.bat text eol=crlf
\ No newline at end of file
diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml
new file mode 100644
index 0000000..d402f3d
--- /dev/null
+++ b/.github/actions/setup/action.yml
@@ -0,0 +1,27 @@
+name: Setup
+description: Setup Node.js and install dependencies
+
+runs:
+ using: composite
+ steps:
+ - name: Setup Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version-file: .nvmrc
+
+ - name: Cache dependencies
+ id: yarn-cache
+ uses: actions/cache@v3
+ with:
+ path: |
+ **/node_modules
+ key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-yarn-
+
+ - name: Install dependencies
+ if: steps.yarn-cache.outputs.cache-hit != 'true'
+ run: |
+ yarn install --cwd example --frozen-lockfile
+ yarn install --frozen-lockfile
+ shell: bash
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..9c5ee1f
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,48 @@
+name: CI
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Setup
+ uses: ./.github/actions/setup
+
+ - name: Lint files
+ run: yarn lint
+
+ - name: Typecheck files
+ run: yarn typecheck
+
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Setup
+ uses: ./.github/actions/setup
+
+ - name: Run unit tests
+ run: yarn test --maxWorkers=2 --coverage
+
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Setup
+ uses: ./.github/actions/setup
+
+ - name: Build package
+ run: yarn prepack
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7535671
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,70 @@
+# OSX
+#
+.DS_Store
+
+# XDE
+.expo/
+
+# VSCode
+.vscode/
+jsconfig.json
+
+# Xcode
+#
+build/
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata
+*.xccheckout
+*.moved-aside
+DerivedData
+*.hmap
+*.ipa
+*.xcuserstate
+project.xcworkspace
+
+# Android/IJ
+#
+.classpath
+.cxx
+.gradle
+.idea
+.project
+.settings
+local.properties
+android.iml
+
+# Cocoapods
+#
+example/ios/Pods
+
+# Ruby
+example/vendor/
+
+# node.js
+#
+node_modules/
+npm-debug.log
+yarn-debug.log
+yarn-error.log
+
+# BUCK
+buck-out/
+\.buckd/
+android/app/libs
+android/keystores/debug.keystore
+
+# Expo
+.expo/
+
+# Turborepo
+.turbo/
+
+# generated by bob
+lib/
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..5397c87
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+16.18.1
diff --git a/.watchmanconfig b/.watchmanconfig
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/.watchmanconfig
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/.yarnrc b/.yarnrc
new file mode 100644
index 0000000..fedc0f1
--- /dev/null
+++ b/.yarnrc
@@ -0,0 +1,3 @@
+# Override Yarn command so we can automatically setup the repo on running `yarn`
+
+yarn-path "scripts/bootstrap.js"
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..45d257b
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,133 @@
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+[INSERT CONTACT METHOD].
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..0b14c41
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,143 @@
+# Contributing
+
+Contributions are always welcome, no matter how large or small!
+
+We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. Before contributing, please read the [code of conduct](./CODE_OF_CONDUCT.md).
+
+## Development workflow
+
+To get started with the project, run `yarn` in the root directory to install the required dependencies for each package:
+
+```sh
+yarn
+```
+
+> While it's possible to use [`npm`](https://github.com/npm/cli), the tooling is built around [`yarn`](https://classic.yarnpkg.com/), so you'll have an easier time if you use `yarn` for development.
+
+While developing, you can run the [example app](/example/) to test your changes. Any changes you make in your library's JavaScript code will be reflected in the example app without a rebuild. If you change any native code, then you'll need to rebuild the example app.
+
+To start the packager:
+
+```sh
+yarn example start
+```
+
+To run the example app on Android:
+
+```sh
+yarn example android
+```
+
+To run the example app on iOS:
+
+```sh
+yarn example ios
+```
+
+By default, the example is configured to build with the old architecture. To run the example with the new architecture, you can do the following:
+
+1. For Android, run:
+
+ ```sh
+ ORG_GRADLE_PROJECT_newArchEnabled=true yarn example android
+ ```
+
+2. For iOS, run:
+
+ ```sh
+ RCT_NEW_ARCH_ENABLED=1 yarn example pods
+ yarn example ios
+ ```
+
+If you are building for a different architecture than your previous build, make sure to remove the build folders first. You can run the following command to cleanup all build folders:
+
+```sh
+yarn clean
+```
+
+To confirm that the app is running with the new architecture, you can check the Metro logs for a message like this:
+
+```sh
+Running "RtnGimbalAirshipAdapterExample" with {"fabric":true,"initialProps":{"concurrentRoot":true},"rootTag":1}
+```
+
+Note the `"fabric":true` and `"concurrentRoot":true` properties.
+
+Make sure your code passes TypeScript and ESLint. Run the following to verify:
+
+```sh
+yarn typecheck
+yarn lint
+```
+
+To fix formatting errors, run the following:
+
+```sh
+yarn lint --fix
+```
+
+Remember to add tests for your change if possible. Run the unit tests by:
+
+```sh
+yarn test
+```
+
+To edit the Objective-C or Swift files, open `example/ios/RtnGimbalAirshipAdapterExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > rtn-gimbal-airship-adapter`.
+
+To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `rtn-gimbal-airship-adapter` under `Android`.
+
+
+### Commit message convention
+
+We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:
+
+- `fix`: bug fixes, e.g. fix crash due to deprecated method.
+- `feat`: new features, e.g. add new method to the module.
+- `refactor`: code refactor, e.g. migrate from class components to hooks.
+- `docs`: changes into documentation, e.g. add usage example for the module..
+- `test`: adding or updating tests, e.g. add integration tests using detox.
+- `chore`: tooling changes, e.g. change CI config.
+
+Our pre-commit hooks verify that your commit message matches this format when committing.
+
+### Linting and tests
+
+[ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/)
+
+We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing.
+
+Our pre-commit hooks verify that the linter and tests pass when committing.
+
+### Publishing to npm
+
+We use [release-it](https://github.com/release-it/release-it) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc.
+
+To publish new versions, run the following:
+
+```sh
+yarn release
+```
+
+### Scripts
+
+The `package.json` file contains various scripts for common tasks:
+
+- `yarn bootstrap`: setup project by installing all dependencies and pods.
+- `yarn typecheck`: type-check files with TypeScript.
+- `yarn lint`: lint files with ESLint.
+- `yarn test`: run unit tests with Jest.
+- `yarn example start`: start the Metro server for the example app.
+- `yarn example android`: run the example app on Android.
+- `yarn example ios`: run the example app on iOS.
+
+### Sending a pull request
+
+> **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).
+
+When you're sending a pull request:
+
+- Prefer small pull requests focused on one change.
+- Verify that linters and tests are passing.
+- Review the documentation to make sure it looks good.
+- Follow the pull request template when opening a pull request.
+- For pull requests that change the API or implementation, discuss with maintainers first by opening an issue.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..58a5b9a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+MIT License
+
+Copyright (c) 2022 Andrew Tran
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4509b02
--- /dev/null
+++ b/README.md
@@ -0,0 +1,31 @@
+# rtn-gimbal-airship-adapter
+
+A React Native adapter for Gimbal and Urban Airship.
+
+## Installation
+
+```sh
+npm install rtn-gimbal-airship-adapter
+```
+
+## Usage
+
+```js
+import { multiply } from 'rtn-gimbal-airship-adapter';
+
+// ...
+
+const result = await multiply(3, 7);
+```
+
+## Contributing
+
+See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
+
+## License
+
+MIT
+
+---
+
+Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..30b5e44
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,87 @@
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath "com.android.tools.build:gradle:7.2.1"
+ }
+}
+
+def isNewArchitectureEnabled() {
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
+}
+
+apply plugin: "com.android.library"
+
+if (isNewArchitectureEnabled()) {
+ apply plugin: "com.facebook.react"
+}
+
+def getExtOrDefault(name) {
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["RtnGimbalAirshipAdapter_" + name]
+}
+
+def getExtOrIntegerDefault(name) {
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["RtnGimbalAirshipAdapter_" + name]).toInteger()
+}
+
+android {
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
+
+ defaultConfig {
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ }
+ }
+
+ lintOptions {
+ disable "GradleCompatible"
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ sourceSets {
+ main {
+ if (isNewArchitectureEnabled()) {
+ java.srcDirs += [
+ "src/newarch",
+ // This is needed to build Kotlin project with NewArch enabled
+ "${project.buildDir}/generated/source/codegen/java"
+ ]
+ } else {
+ java.srcDirs += ["src/oldarch"]
+ }
+ }
+ }
+}
+
+repositories {
+ mavenCentral()
+ google()
+}
+
+
+dependencies {
+ // For < 0.71, this will be from the local maven repo
+ // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
+ //noinspection GradleDynamicVersion
+ implementation "com.facebook.react:react-native"
+}
+
+if (isNewArchitectureEnabled()) {
+ react {
+ jsRootDir = file("../src/")
+ libraryName = "RtnGimbalAirshipAdapter"
+ codegenJavaPackageName = "com.rtngimbalairshipadapter"
+ }
+}
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000..d01bc20
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,5 @@
+RtnGimbalAirshipAdapter_kotlinVersion=1.7.0
+RtnGimbalAirshipAdapter_minSdkVersion=21
+RtnGimbalAirshipAdapter_targetSdkVersion=31
+RtnGimbalAirshipAdapter_compileSdkVersion=31
+RtnGimbalAirshipAdapter_ndkversion=21.4.7075529
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..fec3a9e
--- /dev/null
+++ b/android/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/android/src/main/java/com/rtngimbalairshipadapter/RtnGimbalAirshipAdapterModule.java b/android/src/main/java/com/rtngimbalairshipadapter/RtnGimbalAirshipAdapterModule.java
new file mode 100644
index 0000000..0004e6a
--- /dev/null
+++ b/android/src/main/java/com/rtngimbalairshipadapter/RtnGimbalAirshipAdapterModule.java
@@ -0,0 +1,29 @@
+package com.rtngimbalairshipadapter;
+
+import androidx.annotation.NonNull;
+
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactMethod;
+
+public class RtnGimbalAirshipAdapterModule extends RtnGimbalAirshipAdapterSpec {
+ public static final String NAME = "RtnGimbalAirshipAdapter";
+
+ RtnGimbalAirshipAdapterModule(ReactApplicationContext context) {
+ super(context);
+ }
+
+ @Override
+ @NonNull
+ public String getName() {
+ return NAME;
+ }
+
+
+ // Example method
+ // See https://reactnative.dev/docs/native-modules-android
+ @ReactMethod
+ public void multiply(double a, double b, Promise promise) {
+ promise.resolve(a * b);
+ }
+}
diff --git a/android/src/main/java/com/rtngimbalairshipadapter/RtnGimbalAirshipAdapterPackage.java b/android/src/main/java/com/rtngimbalairshipadapter/RtnGimbalAirshipAdapterPackage.java
new file mode 100644
index 0000000..15d0a0a
--- /dev/null
+++ b/android/src/main/java/com/rtngimbalairshipadapter/RtnGimbalAirshipAdapterPackage.java
@@ -0,0 +1,45 @@
+package com.rtngimbalairshipadapter;
+
+import androidx.annotation.Nullable;
+
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.module.model.ReactModuleInfo;
+import com.facebook.react.module.model.ReactModuleInfoProvider;
+import com.facebook.react.TurboReactPackage;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RtnGimbalAirshipAdapterPackage extends TurboReactPackage {
+
+ @Nullable
+ @Override
+ public NativeModule getModule(String name, ReactApplicationContext reactContext) {
+ if (name.equals(RtnGimbalAirshipAdapterModule.NAME)) {
+ return new RtnGimbalAirshipAdapterModule(reactContext);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public ReactModuleInfoProvider getReactModuleInfoProvider() {
+ return () -> {
+ final Map moduleInfos = new HashMap<>();
+ boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
+ moduleInfos.put(
+ RtnGimbalAirshipAdapterModule.NAME,
+ new ReactModuleInfo(
+ RtnGimbalAirshipAdapterModule.NAME,
+ RtnGimbalAirshipAdapterModule.NAME,
+ false, // canOverrideExistingModule
+ false, // needsEagerInit
+ true, // hasConstants
+ false, // isCxxModule
+ isTurboModule // isTurboModule
+ ));
+ return moduleInfos;
+ };
+ }
+}
diff --git a/android/src/newarch/RtnGimbalAirshipAdapterSpec.java b/android/src/newarch/RtnGimbalAirshipAdapterSpec.java
new file mode 100644
index 0000000..fb6db48
--- /dev/null
+++ b/android/src/newarch/RtnGimbalAirshipAdapterSpec.java
@@ -0,0 +1,9 @@
+package com.rtngimbalairshipadapter;
+
+import com.facebook.react.bridge.ReactApplicationContext;
+
+abstract class RtnGimbalAirshipAdapterSpec extends NativeRtnGimbalAirshipAdapterSpec {
+ RtnGimbalAirshipAdapterSpec(ReactApplicationContext context) {
+ super(context);
+ }
+}
diff --git a/android/src/oldarch/RtnGimbalAirshipAdapterSpec.java b/android/src/oldarch/RtnGimbalAirshipAdapterSpec.java
new file mode 100644
index 0000000..ad8b7f8
--- /dev/null
+++ b/android/src/oldarch/RtnGimbalAirshipAdapterSpec.java
@@ -0,0 +1,13 @@
+package com.rtngimbalairshipadapter;
+
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.Promise;
+
+abstract class RtnGimbalAirshipAdapterSpec extends ReactContextBaseJavaModule {
+ RtnGimbalAirshipAdapterSpec(ReactApplicationContext context) {
+ super(context);
+ }
+
+ public abstract void multiply(double a, double b, Promise promise);
+}
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 0000000..f842b77
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ presets: ['module:metro-react-native-babel-preset'],
+};
diff --git a/example/.bundle/config b/example/.bundle/config
new file mode 100644
index 0000000..848943b
--- /dev/null
+++ b/example/.bundle/config
@@ -0,0 +1,2 @@
+BUNDLE_PATH: "vendor/bundle"
+BUNDLE_FORCE_RUBY_PLATFORM: 1
diff --git a/example/.node-version b/example/.node-version
new file mode 100644
index 0000000..3c03207
--- /dev/null
+++ b/example/.node-version
@@ -0,0 +1 @@
+18
diff --git a/example/.ruby-version b/example/.ruby-version
new file mode 100644
index 0000000..49cdd66
--- /dev/null
+++ b/example/.ruby-version
@@ -0,0 +1 @@
+2.7.6
diff --git a/example/.watchmanconfig b/example/.watchmanconfig
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/example/.watchmanconfig
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/example/Gemfile b/example/Gemfile
new file mode 100644
index 0000000..567e598
--- /dev/null
+++ b/example/Gemfile
@@ -0,0 +1,6 @@
+source 'https://rubygems.org'
+
+# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
+ruby File.read(File.join(__dir__, '.ruby-version')).strip
+
+gem 'cocoapods', '~> 1.11', '>= 1.11.3'
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
new file mode 100644
index 0000000..742008b
--- /dev/null
+++ b/example/android/app/build.gradle
@@ -0,0 +1,170 @@
+apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
+
+import com.android.build.OutputFile
+
+/**
+ * This is the configuration block to customize your React Native Android app.
+ * By default you don't need to apply any configuration, just uncomment the lines you need.
+ */
+react {
+ /* Folders */
+ // The root of your project, i.e. where "package.json" lives. Default is '..'
+ // root = file("../")
+ // The folder where the react-native NPM package is. Default is ../node_modules/react-native
+ // reactNativeDir = file("../node_modules/react-native")
+ // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen
+ // codegenDir = file("../node_modules/react-native-codegen")
+ // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
+ // cliFile = file("../node_modules/react-native/cli.js")
+
+ /* Variants */
+ // The list of variants to that are debuggable. For those we're going to
+ // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
+ // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
+ // debuggableVariants = ["liteDebug", "prodDebug"]
+
+ /* Bundling */
+ // A list containing the node command and its flags. Default is just 'node'.
+ // nodeExecutableAndArgs = ["node"]
+ //
+ // The command to run when bundling. By default is 'bundle'
+ // bundleCommand = "ram-bundle"
+ //
+ // The path to the CLI configuration file. Default is empty.
+ // bundleConfig = file(../rn-cli.config.js)
+ //
+ // The name of the generated asset file containing your JS bundle
+ // bundleAssetName = "MyApplication.android.bundle"
+ //
+ // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
+ // entryFile = file("../js/MyApplication.android.js")
+ //
+ // A list of extra flags to pass to the 'bundle' commands.
+ // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
+ // extraPackagerArgs = []
+
+ /* Hermes Commands */
+ // The hermes compiler command to run. By default it is 'hermesc'
+ // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
+ //
+ // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
+ // hermesFlags = ["-O", "-output-source-map"]
+}
+
+/**
+ * Set this to true to create four separate APKs instead of one,
+ * one for each native architecture. This is useful if you don't
+ * use App Bundles (https://developer.android.com/guide/app-bundle/)
+ * and want to have separate APKs to upload to the Play Store.
+ */
+def enableSeparateBuildPerCPUArchitecture = false
+
+/**
+ * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
+ */
+def enableProguardInReleaseBuilds = false
+
+/**
+ * The preferred build flavor of JavaScriptCore (JSC)
+ *
+ * For example, to use the international variant, you can use:
+ * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
+ *
+ * The international variant includes ICU i18n library and necessary data
+ * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
+ * give correct results when using with locales other than en-US. Note that
+ * this variant is about 6MiB larger per architecture than default.
+ */
+def jscFlavor = 'org.webkit:android-jsc:+'
+
+/**
+ * Private function to get the list of Native Architectures you want to build.
+ * This reads the value from reactNativeArchitectures in your gradle.properties
+ * file and works together with the --active-arch-only flag of react-native run-android.
+ */
+def reactNativeArchitectures() {
+ def value = project.getProperties().get("reactNativeArchitectures")
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
+}
+
+android {
+ ndkVersion rootProject.ext.ndkVersion
+
+ compileSdkVersion rootProject.ext.compileSdkVersion
+
+ namespace "com.rtngimbalairshipadapterexample"
+ defaultConfig {
+ applicationId "com.rtngimbalairshipadapterexample"
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+ versionCode 1
+ versionName "1.0"
+ }
+
+ splits {
+ abi {
+ reset()
+ enable enableSeparateBuildPerCPUArchitecture
+ universalApk false // If true, also generate a universal APK
+ include (*reactNativeArchitectures())
+ }
+ }
+ signingConfigs {
+ debug {
+ storeFile file('debug.keystore')
+ storePassword 'android'
+ keyAlias 'androiddebugkey'
+ keyPassword 'android'
+ }
+ }
+ buildTypes {
+ debug {
+ signingConfig signingConfigs.debug
+ }
+ release {
+ // Caution! In production, you need to generate your own keystore file.
+ // see https://reactnative.dev/docs/signed-apk-android.
+ signingConfig signingConfigs.debug
+ minifyEnabled enableProguardInReleaseBuilds
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
+ }
+ }
+
+ // applicationVariants are e.g. debug, release
+ applicationVariants.all { variant ->
+ variant.outputs.each { output ->
+ // For each separate APK per architecture, set a unique version code as described here:
+ // https://developer.android.com/studio/build/configure-apk-splits.html
+ // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
+ def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
+ def abi = output.getFilter(OutputFile.ABI)
+ if (abi != null) { // null for the universal-debug, universal-release variants
+ output.versionCodeOverride =
+ defaultConfig.versionCode * 1000 + versionCodes.get(abi)
+ }
+
+ }
+ }
+}
+
+dependencies {
+ // The version of react-native is set by the React Native Gradle Plugin
+ implementation("com.facebook.react:react-android")
+
+ implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
+
+ debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
+ debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
+ exclude group:'com.squareup.okhttp3', module:'okhttp'
+ }
+
+ debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
+ if (hermesEnabled.toBoolean()) {
+ implementation("com.facebook.react:hermes-android")
+ } else {
+ implementation jscFlavor
+ }
+}
+
+apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
diff --git a/example/android/app/debug.keystore b/example/android/app/debug.keystore
new file mode 100644
index 0000000..364e105
Binary files /dev/null and b/example/android/app/debug.keystore differ
diff --git a/example/android/app/proguard-rules.pro b/example/android/app/proguard-rules.pro
new file mode 100644
index 0000000..11b0257
--- /dev/null
+++ b/example/android/app/proguard-rules.pro
@@ -0,0 +1,10 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..4b185bc
--- /dev/null
+++ b/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/debug/java/com/rtngimbalairshipadapterexample/ReactNativeFlipper.java b/example/android/app/src/debug/java/com/rtngimbalairshipadapterexample/ReactNativeFlipper.java
new file mode 100644
index 0000000..c2169ff
--- /dev/null
+++ b/example/android/app/src/debug/java/com/rtngimbalairshipadapterexample/ReactNativeFlipper.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ *
This source code is licensed under the MIT license found in the LICENSE file in the root
+ * directory of this source tree.
+ */
+package com.rtngimbalairshipadapterexample;
+
+import android.content.Context;
+import com.facebook.flipper.android.AndroidFlipperClient;
+import com.facebook.flipper.android.utils.FlipperUtils;
+import com.facebook.flipper.core.FlipperClient;
+import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
+import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
+import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
+import com.facebook.flipper.plugins.inspector.DescriptorMapping;
+import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
+import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
+import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
+import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
+import com.facebook.react.ReactInstanceEventListener;
+import com.facebook.react.ReactInstanceManager;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.modules.network.NetworkingModule;
+import okhttp3.OkHttpClient;
+
+/**
+ * Class responsible of loading Flipper inside your React Native application. This is the debug
+ * flavor of it. Here you can add your own plugins and customize the Flipper setup.
+ */
+public class ReactNativeFlipper {
+ public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
+ if (FlipperUtils.shouldEnableFlipper(context)) {
+ final FlipperClient client = AndroidFlipperClient.getInstance(context);
+
+ client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
+ client.addPlugin(new DatabasesFlipperPlugin(context));
+ client.addPlugin(new SharedPreferencesFlipperPlugin(context));
+ client.addPlugin(CrashReporterPlugin.getInstance());
+
+ NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
+ NetworkingModule.setCustomClientBuilder(
+ new NetworkingModule.CustomClientBuilder() {
+ @Override
+ public void apply(OkHttpClient.Builder builder) {
+ builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
+ }
+ });
+ client.addPlugin(networkFlipperPlugin);
+ client.start();
+
+ // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
+ // Hence we run if after all native modules have been initialized
+ ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
+ if (reactContext == null) {
+ reactInstanceManager.addReactInstanceEventListener(
+ new ReactInstanceEventListener() {
+ @Override
+ public void onReactContextInitialized(ReactContext reactContext) {
+ reactInstanceManager.removeReactInstanceEventListener(this);
+ reactContext.runOnNativeModulesQueueThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ client.addPlugin(new FrescoFlipperPlugin());
+ }
+ });
+ }
+ });
+ } else {
+ client.addPlugin(new FrescoFlipperPlugin());
+ }
+ }
+ }
+}
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..4122f36
--- /dev/null
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/java/com/rtngimbalairshipadapterexample/MainActivity.java b/example/android/app/src/main/java/com/rtngimbalairshipadapterexample/MainActivity.java
new file mode 100644
index 0000000..7a8f185
--- /dev/null
+++ b/example/android/app/src/main/java/com/rtngimbalairshipadapterexample/MainActivity.java
@@ -0,0 +1,35 @@
+package com.rtngimbalairshipadapterexample;
+
+import com.facebook.react.ReactActivity;
+import com.facebook.react.ReactActivityDelegate;
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
+import com.facebook.react.defaults.DefaultReactActivityDelegate;
+
+public class MainActivity extends ReactActivity {
+
+ /**
+ * Returns the name of the main component registered from JavaScript. This is used to schedule
+ * rendering of the component.
+ */
+ @Override
+ protected String getMainComponentName() {
+ return "RtnGimbalAirshipAdapterExample";
+ }
+
+ /**
+ * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
+ * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
+ * (aka React 18) with two boolean flags.
+ */
+ @Override
+ protected ReactActivityDelegate createReactActivityDelegate() {
+ return new DefaultReactActivityDelegate(
+ this,
+ getMainComponentName(),
+ // If you opted-in for the New Architecture, we enable the Fabric Renderer.
+ DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled
+ // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18).
+ DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled
+ );
+ }
+}
diff --git a/example/android/app/src/main/java/com/rtngimbalairshipadapterexample/MainApplication.java b/example/android/app/src/main/java/com/rtngimbalairshipadapterexample/MainApplication.java
new file mode 100644
index 0000000..79e64ef
--- /dev/null
+++ b/example/android/app/src/main/java/com/rtngimbalairshipadapterexample/MainApplication.java
@@ -0,0 +1,62 @@
+package com.rtngimbalairshipadapterexample;
+
+import android.app.Application;
+import com.facebook.react.PackageList;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
+import com.facebook.react.defaults.DefaultReactNativeHost;
+import com.facebook.soloader.SoLoader;
+import java.util.List;
+
+public class MainApplication extends Application implements ReactApplication {
+
+ private final ReactNativeHost mReactNativeHost =
+ new DefaultReactNativeHost(this) {
+ @Override
+ public boolean getUseDeveloperSupport() {
+ return BuildConfig.DEBUG;
+ }
+
+ @Override
+ protected List getPackages() {
+ @SuppressWarnings("UnnecessaryLocalVariable")
+ List packages = new PackageList(this).getPackages();
+ // Packages that cannot be autolinked yet can be added manually here, for example:
+ // packages.add(new MyReactNativePackage());
+ return packages;
+ }
+
+ @Override
+ protected String getJSMainModuleName() {
+ return "index";
+ }
+
+ @Override
+ protected boolean isNewArchEnabled() {
+ return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
+ }
+
+ @Override
+ protected Boolean isHermesEnabled() {
+ return BuildConfig.IS_HERMES_ENABLED;
+ }
+ };
+
+ @Override
+ public ReactNativeHost getReactNativeHost() {
+ return mReactNativeHost;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ SoLoader.init(this, /* native exopackage */ false);
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+ // If you opted-in for the New Architecture, we load the native entry point for this app.
+ DefaultNewArchitectureEntryPoint.load();
+ }
+ ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
+ }
+}
diff --git a/example/android/app/src/main/res/drawable/rn_edit_text_material.xml b/example/android/app/src/main/res/drawable/rn_edit_text_material.xml
new file mode 100644
index 0000000..f35d996
--- /dev/null
+++ b/example/android/app/src/main/res/drawable/rn_edit_text_material.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a2f5908
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1b52399
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..ff10afd
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..115a4c7
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..dcd3cd8
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..459ca60
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..8ca12fe
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..8e19b41
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b824ebd
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..4c19a13
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/values/strings.xml b/example/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3377062
--- /dev/null
+++ b/example/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ RtnGimbalAirshipAdapterExample
+
diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..7ba83a2
--- /dev/null
+++ b/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/example/android/app/src/release/java/com/rtngimbalairshipadapterexample/ReactNativeFlipper.java b/example/android/app/src/release/java/com/rtngimbalairshipadapterexample/ReactNativeFlipper.java
new file mode 100644
index 0000000..f92a9ba
--- /dev/null
+++ b/example/android/app/src/release/java/com/rtngimbalairshipadapterexample/ReactNativeFlipper.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ *