Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

221 cordova capacitor react integration #224

Merged
merged 10 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions docs/enioka-scan-compat-package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Compatibility layer for various android application frameworks

enioka-scan provides npm packages that aim at facilitating its integration within already existing apps.

## For all android projects
You need to add the matching dependencing, depending on what physical device you wish to use.

in ``android/app/build.gradle``
```gradle
dependencies {
//core library
implementation group: 'com.enioka.scanner', name: 'enioka-scan-core', version: '3.0.1'
//use camera
implementation group: 'com.enioka.scanner', name: 'provider-os-camera', version: '3.0.1'

//provider dependant, here is for honeywell scanner.

implementation group: 'com.enioka.scanner', name: 'provider-os-honeywell-integrated', version: '3.0.1'
}
```
*(using the ``mavenCentral()`` repository )*


You can then implement your own logic and Activities by creating a class extending ``ScannerCompatActivity``.

```java
import com.enioka.scanner.activities.ScannerCompatActivity;

public class MyScanActivity extends ScannerCompatActivity {

@Override
public void initCamera(){
super.initCamera();

//initCamera logic...
}

@Override
public void onData(List<Barcode> data)
{
//onData Logic
}

//rest of the Activity logic
}

```

## Cordova
Cordova has its own plugin system
You can add the compat library using

```bash
$ cordova plugin add enioka-scan-compat
```

in any .js file :

```js

function foo()
{
window.startActivityNow(
{className:"com.example.myapp.MyScanActivity"},
successHandler,
errorHandler
)
}
```


## Capacitor
Capcitor supports cordova modules installed with npm

``` bash
$ npm install enioka-scan-compat-
```



```html
<script src="js/index.js" type="module"></script>
```

```js
function foo() {
window.startActivityNow(
{className:"com.example.myapp.MyScanActivity"},
successHandler,
errorHandler
)
}
```

## React Native

``` bash
$ npm install enioka-scan-compat-
```

```tsx
import { startActivity } from 'enioka-scan-compat-'

<Button title = "startActivity" onPress={() => startActivity("com.example.myapp.MyScanActivity")}>
</Button>
```

## Troubleshooting

- in gradle.properties :
``android.enableJetifier=true``
- in AndroidManifest.xml
``android.allowBackup=true``
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le formatting du markdown dans un commentaire de PR sera pas ouf, je peux t'envoyer la version RAW si besoin. Reformulation de certains points et simplification.

Pour la partie heritage de notre activity, comment ca s'integre a leur projet ? Est-ce qu'ils doivent rajouter du code java a un endroit particulier pour que le plugin le detecte ?

Markdown:

Compatibility layer for various android application frameworks

enioka-scan provides npm packages that facilitate its integration with non-java applications by allowing you to use the provided Scanner and Camera activities.

For all android projects

The npm plugins only facilitate the integration of the provided UI, however you still need to add the usual Maven Central dependencies in android/app/build.gradle:

dependencies {
    // core library
    implementation group: 'com.enioka.scanner', name: 'enioka-scan-core', version: 'X.Y.Z'
    // wanted device-specific providers (e.g. Camera and Honeywell integrated)
    implementation group: 'com.enioka.scanner', name: 'provider-os-camera', version: 'X.Y.Z'
    implementation group: 'com.enioka.scanner', name: 'provider-os-honeywell-integrated', version: 'X.Y.Z'
}

Cordova and Capacitor

Cordova has its own plugin system. You can add the integration dependency using:

$ cordova plugin add @enioka/enioka-scan-cordova-capacitor-integration

Capcitor supports Cordova modules installed with npm, it therefore uses the same dependency:

$ npm install @enioka/enioka-scan-cordova-capacitor-integration

You can then easily instantiate the scanner activity in any .js file :

function foo() 
{
    window.startActivityNow(
        { className:"com.enioka.scanner.activities.ScannerCompatActivity" },
        successHandler,
        errorHandler
    )
}

React Native

The React Native integration dependency can be installed with the following command:

$ npm install @enioka/enioka-scan-react-native-integration

You can then easily instantiate the scanner activity in any .js file used in your HTML page:

import { startActivity } from 'enioka-scan-react-native-integration'

<Button title = "startActivity" onPress={() => startActivity("com.enioka.scanner.activities.ScannerCompatActivity")}>
</Button>

Troubleshooting

Because your application's manifest will have to be merged with the enioka Scan dependencies, make sure the following properties match the ones used in enioka Scan (which are not the default values):

  • in gradle.properties:
    android.enableJetifier=true
  • in AndroidManifest.xml:
    android.allowBackup=true

Improvements

So far this setup only allows the launch of an activity without much control on their intent extras, and without much thought put into the Service aspect, as these frameworks are primarily UI-oriented and not designed for deep Android integration.

This means:

  • We do not provide any means to easily bind to the Scanner service independently from the provided ScannerCompatActivity. The service should still be available after installing the core dependency, so your franework may offer a way to bind to it.
  • We do not provide any means to easily extend the UI beyond simply launching the default one, you may be able to extend it in a Java class and use this class in the startActivity() call instead, but Java will still be needed.
  • We do not provide any way to customize the startActivity() intent for now though that will be a feature down the line.

21 changes: 21 additions & 0 deletions npm_integration_frameworks/cordova-capacitor/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@enioka/enioka-scan-cordova-capacitor-integration",
"version": "0.1.0",
"description": "enioka scan plugin cordova",
"main": "main.js",
"cordova": {
"id": "enioka-scan-cordova-capacitor-integration",
"platforms": [
"android"
]
},
"keywords": [
"enioka",
"enioka-scan",
"scanner",
"integration-layer",
"capacitor"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"capacitor"
"capacitor",
"cordova",
"plugin"

],
"author": "enioka",
"license": "MIT"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"license": "MIT"
"license": "Apache-2.0"

}
28 changes: 28 additions & 0 deletions npm_integration_frameworks/cordova-capacitor/plugin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="enioka-scan-cordova-capacitor-integration"
version="0.1.0">

<name>ActivityStarterPlugin</name>

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

<asset src="www/main.js" target="js/main.js"/>

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

<platform name="android">

<config-file target="res/xml/config.xml" parent="/*">
<feature name="ActivityStarterPlugin">
<param name="android-package" value="com.enioka.plugin.ActivityStarterPlugin"/>
</feature>
</config-file>

<source-file src="src/android/ActivityStarterPlugin.java" target-dir="src/com/enioka/plugin/"/>
</platform>
</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import android.content.Intent;
import android.util.Log;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import java.lang.ClassNotFoundException;

public class ActivityStarterPlugin extends CordovaPlugin {

private static final String LOG_TAG = "ActivityStarter";
private static final String startActivityActionName = "startActivity";

public ActivityStarterPlugin() {
}
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext)
{
String targetActivityName = "";
Class<?> klass;
Log.d(LOG_TAG, "Received Action: " + action);

if (action.equals(startActivityActionName)){
try {
targetActivityName = args.getJSONObject(0).getString("targetActivityName");
Log.d(LOG_TAG, "targetActivityName : " + targetActivityName);
klass = Class.forName(targetActivityName);
}
catch(ClassNotFoundException e){
Log.e(LOG_TAG, e.toString());
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION));
return false;
}
catch (JSONException e){
Log.e(LOG_TAG, e.toString());
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR));
return false;
}

Intent intent = new Intent(this.cordova.getContext(), klass);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ca pourrait etre bien de supporter un bundle / des extras a integrer a cet intent, pour permettre a l'utilisateur de controller les options de l'application (voir app de demo pour comment ce serait utilise). C'est ok si pas evident tout de suite, ca peut attendre une autre MR.

this.cordova.getActivity().startActivity(intent);
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
return true;
}

Log.e(LOG_TAG, "Invalid Action");
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
return false;
}
}
5 changes: 5 additions & 0 deletions npm_integration_frameworks/cordova-capacitor/www/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var exec = require('cordova/exec');

window.startActivity = function (params, successCallback, errorCallback) {
exec(successCallback, errorCallback, "ActivityStarterPlugin", "startActivity", [params]);
};
3 changes: 3 additions & 0 deletions npm_integration_frameworks/reactnative/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.pbxproj -text
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gitattributes pas necessaire, a supprimer

# specific for windows script files
*.bat text eol=crlf
82 changes: 82 additions & 0 deletions npm_integration_frameworks/reactnative/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# OSX
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Si le .gitignore racine n'est pas suffisamment complet, ajouter dedans les champs qui manquent plutot que d'utiliser un deuxieme gitignore. Celui ci sera a supprimer

#
.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

# Yarn
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Expo
.expo/

# Turborepo
.turbo/

# generated by bob
lib/

# React Native Codegen
ios/generated
android/generated
1 change: 1 addition & 0 deletions npm_integration_frameworks/reactnative/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v18

Large diffs are not rendered by default.

Large diffs are not rendered by default.

874 changes: 874 additions & 0 deletions npm_integration_frameworks/reactnative/.yarn/releases/yarn-3.6.1.cjs

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions npm_integration_frameworks/reactnative/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
nodeLinker: node-modules
nmHoistingLimits: workspaces

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"

yarnPath: .yarn/releases/yarn-3.6.1.cjs
Loading