@gatekeeperx/cordova-plugin-devicex 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +11 -0
- package/README.md +484 -0
- package/package.json +46 -0
- package/plugin.xml +50 -0
- package/src/android/com/gatekeeperx/cordova/DevicexPlugin.java +204 -0
- package/src/android/hooks/configure-gradle.js +62 -0
- package/src/android/libs/devicex-1.2.5.aar +0 -0
- package/src/android/libs/devicex-bridge.aar +0 -0
- package/types/index.d.ts +52 -0
- package/www/devicex.js +28 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
## [1.0.0] - 2026-01-19
|
|
3
|
+
### Added
|
|
4
|
+
- Initial release
|
|
5
|
+
- Android support with cordova-android >= 11
|
|
6
|
+
- Pre-compiled AAR bridge (Kotlin)
|
|
7
|
+
- Device Intelligence SDK integration
|
|
8
|
+
- Auto-configuration via plugin variables
|
|
9
|
+
- TypeScript definitions
|
package/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Apache License 2.0
|
|
2
|
+
Copyright 2026 GatekeeperX
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software
|
|
8
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
|
+
See the License for the specific language governing permissions and
|
|
11
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
# cordova-plugin-devicex
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/cordova-plugin-devicex)
|
|
4
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
|
+
|
|
6
|
+
Plugin Cordova oficial que expone la potencia del SDK nativo **GatekeeperX Device Intelligence Android**. Actúa como un **Bridge** directo hacia la librería `device-intelligence-android`, exponiendo capacidades de fingerprinting profundo, detección de fraude y telemetría de seguridad en tiempo real.
|
|
7
|
+
|
|
8
|
+
## 🚀 Features
|
|
9
|
+
|
|
10
|
+
- ✅ **Detección de rooting/jailbreak** (Magisk, Frida, Xposed, Superuser)
|
|
11
|
+
- ✅ **Identificación de emuladores** (AVD, Genymotion, Bluestacks)
|
|
12
|
+
- ✅ **Risk scoring** basado en +50 señales del dispositivo
|
|
13
|
+
- ✅ **Deep Fingerprinting**:
|
|
14
|
+
- 🔋 Batería & Energía
|
|
15
|
+
- 📷 Cámaras & Codecs
|
|
16
|
+
- 💾 CPU, GPU & Memoria
|
|
17
|
+
- 📡 Sensores & Input Devices
|
|
18
|
+
- 📦 Package Manager & Settings
|
|
19
|
+
- ✅ **Event tracking** con telemetría de seguridad automática
|
|
20
|
+
- ✅ **Configuración manual** flexible desde el código
|
|
21
|
+
- ✅ **TypeScript definitions** incluidas
|
|
22
|
+
- ✅ **Integration Bridge**: Mapeo directo 1:1 con `device-intelligence-android`
|
|
23
|
+
- ✅ **Soporte cordova-android >= 11**
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 📋 Tabla de Contenidos
|
|
28
|
+
|
|
29
|
+
- [Requisitos](#-requisitos)
|
|
30
|
+
- [Instalación](#-instalación)
|
|
31
|
+
- [Uso](#-uso)
|
|
32
|
+
- [Ejemplos básicos](#ejemplos-básicos)
|
|
33
|
+
- [Casos de uso reales](#casos-de-uso-reales)
|
|
34
|
+
- [API Reference](#-api-reference)
|
|
35
|
+
- [Configuración avanzada](#-configuración-avanzada)
|
|
36
|
+
- [Seguridad y mejores prácticas](#-seguridad-y-mejores-prácticas)
|
|
37
|
+
- [Solución de problemas](#-solución-de-problemas)
|
|
38
|
+
- [Desarrollo y contribución](#-desarrollo-y-contribución)
|
|
39
|
+
- [Licencia](#licencia)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## ⚡ Quick Start
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# 1. Instalar plugin desde npm
|
|
47
|
+
ionic cordova plugin add cordova-plugin-devicex
|
|
48
|
+
|
|
49
|
+
# 2. Agregar plataforma Android 11+
|
|
50
|
+
ionic cordova platform add android@11
|
|
51
|
+
|
|
52
|
+
# 3. Construir
|
|
53
|
+
ionic cordova build android
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Uso en tu app:**
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
declare const Devicex: any;
|
|
60
|
+
|
|
61
|
+
// El SDK debe ser inicializado manualmente antes de su uso
|
|
62
|
+
await Devicex.configure({
|
|
63
|
+
tenant: 'gatekeeperx',
|
|
64
|
+
apiKey: 'tu-api-key',
|
|
65
|
+
environment: 'SANDBOX'
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Enviar eventos con telemetría de seguridad automática
|
|
69
|
+
const result = await Devicex.sendEvent('app_start');
|
|
70
|
+
console.log('Event sent:', result.ok, 'DeviceXId:', result.deviceXId);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 📦 Requisitos
|
|
76
|
+
|
|
77
|
+
- **Node.js** y npm
|
|
78
|
+
- **Java JDK 11 o 17** (para cordova-android 11+)
|
|
79
|
+
- **Android SDK** instalado y configurado
|
|
80
|
+
- **Ionic CLI** (si usas Ionic)
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Configurar Java y Android SDK
|
|
84
|
+
export JAVA_HOME="$(/usr/libexec/java_home -v 17)"
|
|
85
|
+
export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 🔧 Instalación
|
|
91
|
+
|
|
92
|
+
### Desde npm (recomendado)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
ionic cordova plugin add cordova-plugin-devicex
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Agregar plataforma Android
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
ionic cordova platform add android@11
|
|
102
|
+
# O versión superior (12, 13, etc.)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Construir y ejecutar
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Build
|
|
109
|
+
ionic cordova build android
|
|
110
|
+
|
|
111
|
+
# Ejecutar en dispositivo
|
|
112
|
+
ionic cordova run android --device
|
|
113
|
+
|
|
114
|
+
# Ejecutar en emulador
|
|
115
|
+
ionic cordova run android --emulator
|
|
116
|
+
|
|
117
|
+
# Ver logs
|
|
118
|
+
adb logcat | grep -i -E "devicex|gatekeeperx"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 💻 Uso
|
|
124
|
+
|
|
125
|
+
### Declaración TypeScript
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// Declarar el objeto global Devicex
|
|
129
|
+
declare const Devicex: any;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Ejemplos básicos
|
|
133
|
+
|
|
134
|
+
#### 1. Verificar inicialización
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const initialized = await Devicex.isInitialized();
|
|
138
|
+
console.log('SDK initialized:', initialized);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### 2. Obtener versión del SDK
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const version = await Devicex.getVersion();
|
|
145
|
+
console.log('SDK version:', version);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### 3. Enviar evento personalizado
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const result = await Devicex.sendEvent(
|
|
152
|
+
'view_product',
|
|
153
|
+
{ productId: '12345', category: 'electronics' },
|
|
154
|
+
{ 'X-Trace-Id': 'abc-123' }
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
console.log('Event sent:', result.ok);
|
|
158
|
+
console.log('Device ID:', result.deviceXId);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Casos de uso reales
|
|
162
|
+
|
|
163
|
+
### Casos de uso reales
|
|
164
|
+
|
|
165
|
+
#### Login seguro
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
async function handleLogin(username: string, password: string) {
|
|
169
|
+
// Proceder con login
|
|
170
|
+
const loginResult = await authenticate(username, password);
|
|
171
|
+
|
|
172
|
+
// Enviar evento de login (el SDK adjunta fingerprint y risk signals internamente)
|
|
173
|
+
await Devicex.sendEvent('login', {
|
|
174
|
+
method: 'password',
|
|
175
|
+
success: loginResult.success
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Monitoreo de pantallas
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// En tu componente/página (Ionic)
|
|
184
|
+
async ionViewDidEnter() {
|
|
185
|
+
await Devicex.sendEvent('view_screen', {
|
|
186
|
+
screen: 'home',
|
|
187
|
+
timestamp: Date.now()
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 📚 API Reference
|
|
195
|
+
|
|
196
|
+
Este plugin utiliza `DevicexPlugin.kt` para mapear las llamadas JavaScript directamente a los métodos nativos del SDK:
|
|
197
|
+
|
|
198
|
+
| Método JS | Método Nativo (Kotlin) | Descripción |
|
|
199
|
+
|-----------|------------------------|-------------|
|
|
200
|
+
| `configure()` | `Devicex.configure()` | Inicializa el SDK con tu API Key y Tenant. |
|
|
201
|
+
| `sendEvent()` | `Devicex.sendEvent()` | Envía eventos de negocio asegurados con fingerprinting. |
|
|
202
|
+
| `getVersion()` | `Devicex.getVersion()` | Retorna la versión del SDK nativo subyacente. |
|
|
203
|
+
| `isInitialized()` | `Devicex.isInitialized()` | Verifica si la instancia `agent` está lista. |
|
|
204
|
+
|
|
205
|
+
### `Devicex.configure(config)`
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
Configura el SDK. Este paso es obligatorio antes de realizar cualquier otra llamada.
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
await Devicex.configure({
|
|
213
|
+
tenant: 'gatekeeperx',
|
|
214
|
+
apiKey: 'your-api-key',
|
|
215
|
+
environment: 'PRODUCTION', // 'DEVELOPMENT' | 'SANDBOX' | 'PRODUCTION'
|
|
216
|
+
organizationId: 'your-org-id',
|
|
217
|
+
headers: { 'X-Custom-Header': 'value' } // opcional
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Parámetros:**
|
|
222
|
+
- `tenant` (string, requerido): Tenant de GatekeeperX
|
|
223
|
+
- `apiKey` (string, requerido): API Key de autenticación
|
|
224
|
+
- `environment` (string, opcional): Entorno del SDK
|
|
225
|
+
- `organizationId` (string, opcional): ID de organización
|
|
226
|
+
- `headers` (object, opcional): Headers HTTP personalizados
|
|
227
|
+
|
|
228
|
+
**Retorna:** `Promise<void>`
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
### `Devicex.isInitialized()`
|
|
233
|
+
|
|
234
|
+
Verifica si el SDK está inicializado y listo para usarse.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
const initialized = await Devicex.isInitialized();
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Retorna:** `Promise<boolean>`
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
### `Devicex.getVersion()`
|
|
245
|
+
|
|
246
|
+
Obtiene la versión actual del SDK nativo.
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
const version = await Devicex.getVersion();
|
|
250
|
+
// Ejemplo: "1.1.6"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Retorna:** `Promise<string>`
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
### `Devicex.sendEvent(eventType, metadata?, headers?)`
|
|
260
|
+
|
|
261
|
+
Envía un evento personalizado al backend de GatekeeperX.
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
const result = await Devicex.sendEvent(
|
|
265
|
+
'login',
|
|
266
|
+
{ method: 'oauth', provider: 'google' },
|
|
267
|
+
{ 'X-Request-ID': 'abc-123' }
|
|
268
|
+
);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Parámetros:**
|
|
272
|
+
- `eventType` (string, requerido): Tipo de evento (ej: `'login'`, `'checkout'`, `'view_screen'`)
|
|
273
|
+
- `metadata` (object, opcional): Datos adicionales del evento
|
|
274
|
+
- `headers` (object, opcional): Headers HTTP personalizados para esta request
|
|
275
|
+
|
|
276
|
+
**Retorna:** `Promise<EventResult>`
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
interface EventResult {
|
|
280
|
+
ok: boolean; // true si el evento se envió exitosamente
|
|
281
|
+
code?: string; // Código de respuesta del backend
|
|
282
|
+
deviceXId?: string; // ID del dispositivo
|
|
283
|
+
message?: string; // Mensaje de éxito
|
|
284
|
+
errorCode?: string; // Código de error (si ok=false)
|
|
285
|
+
errorMessage?: string; // Mensaje de error (si ok=false)
|
|
286
|
+
httpCode?: number; // Código HTTP de la respuesta
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## ⚙️ Configuración manual
|
|
293
|
+
|
|
294
|
+
Es obligatorio configurar el SDK al inicio de la aplicación:
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
// En tu app.component.ts o main.ts
|
|
298
|
+
async ngOnInit() {
|
|
299
|
+
if (this.platform.is('cordova')) {
|
|
300
|
+
await (window as any).Devicex.configure({
|
|
301
|
+
tenant: 'gatekeeperx',
|
|
302
|
+
apiKey: 'your-api-key',
|
|
303
|
+
environment: 'PRODUCTION',
|
|
304
|
+
organizationId: 'org123'
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Guardias de plataforma
|
|
311
|
+
|
|
312
|
+
Siempre verifica que estás en Cordova antes de usar el plugin:
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { Platform } from '@ionic/angular';
|
|
316
|
+
|
|
317
|
+
constructor(private platform: Platform) {}
|
|
318
|
+
|
|
319
|
+
async doSomething() {
|
|
320
|
+
if (this.platform.is('cordova') && (window as any).Devicex) {
|
|
321
|
+
const risk = await (window as any).Devicex.getRiskAssessment();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 🔒 Seguridad y mejores prácticas
|
|
329
|
+
|
|
330
|
+
### ✅ DO
|
|
331
|
+
|
|
332
|
+
- **Configura el SDK al inicio** mediante el método `configure`
|
|
333
|
+
- **Protege API keys** en CI/CD con secret managers
|
|
334
|
+
- **Usa `DEVELOPMENT`** para desarrollo/pruebas
|
|
335
|
+
- **Usa `PRODUCTION`** solo en builds release
|
|
336
|
+
- **Verifica `platform.is('cordova')`** antes de usar el plugin
|
|
337
|
+
- **Implementa rate limiting** en eventos personalizados
|
|
338
|
+
|
|
339
|
+
### ❌ DON'T
|
|
340
|
+
|
|
341
|
+
- ❌ **No hardcodees** API keys en código fuente
|
|
342
|
+
- ❌ **No commitees** credenciales en Git
|
|
343
|
+
- ❌ **No envíes** PII (datos personales) en metadata de eventos
|
|
344
|
+
- ❌ **No uses** el mismo API key para dev y prod
|
|
345
|
+
|
|
346
|
+
### Ejemplo de integración segura
|
|
347
|
+
|
|
348
|
+
### Ejemplo de integración segura
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
async ionViewDidLoad() {
|
|
352
|
+
if (!this.platform.is('cordova')) return;
|
|
353
|
+
|
|
354
|
+
// El SDK adjuntará automáticamente las señales de seguridad
|
|
355
|
+
const result = await (window as any).Devicex.sendEvent('page_view', {
|
|
356
|
+
page: 'home'
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
console.log('Security telemetry sent:', result.ok);
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## 🛠 Solución de problemas
|
|
366
|
+
|
|
367
|
+
### Error: "class not found" o referencias no resueltas
|
|
368
|
+
|
|
369
|
+
**Causa:** AAR no incluidos o Gradle no configurado correctamente.
|
|
370
|
+
|
|
371
|
+
**Solución:**
|
|
372
|
+
```bash
|
|
373
|
+
# Verifica que existan los AAR
|
|
374
|
+
ls -lh platforms/android/app/libs/devicex*.aar
|
|
375
|
+
|
|
376
|
+
# Re-agregar plugin
|
|
377
|
+
ionic cordova plugin rm cordova-plugin-devicex
|
|
378
|
+
ionic cordova plugin add cordova-plugin-devicex
|
|
379
|
+
|
|
380
|
+
# Limpiar y rebuild
|
|
381
|
+
ionic cordova platform rm android
|
|
382
|
+
ionic cordova platform add android@11
|
|
383
|
+
ionic cordova build android
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
### Error: Conflictos de dependencias Kotlin
|
|
389
|
+
|
|
390
|
+
**Causa:** Versiones incompatibles de Kotlin en tu proyecto.
|
|
391
|
+
|
|
392
|
+
**Solución:**
|
|
393
|
+
|
|
394
|
+
Este plugin usa:
|
|
395
|
+
- `kotlin-stdlib:1.9.25`
|
|
396
|
+
- `kotlinx-coroutines-android:1.7.3`
|
|
397
|
+
|
|
398
|
+
Asegúrate de no forzar versiones diferentes en tu `build.gradle`.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
### Warning: "Mutating configuration after resolution"
|
|
403
|
+
|
|
404
|
+
**Causa:** Warning de Gradle 8.x relacionado con el hook de configuración.
|
|
405
|
+
|
|
406
|
+
**Solución:** Este es un aviso no bloqueante. La build funcionará correctamente. Se resolverá en futuras versiones del plugin.
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
### Plugin no disponible en runtime
|
|
411
|
+
|
|
412
|
+
**Causa:** No verificaste que Cordova esté cargado.
|
|
413
|
+
|
|
414
|
+
**Solución:**
|
|
415
|
+
```typescript
|
|
416
|
+
// Espera a que Cordova esté listo
|
|
417
|
+
this.platform.ready().then(() => {
|
|
418
|
+
if ((window as any).Devicex) {
|
|
419
|
+
// Usa el plugin aquí
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## 🏗 Desarrollo y contribución
|
|
427
|
+
|
|
428
|
+
### Qué incluye este plugin
|
|
429
|
+
|
|
430
|
+
- `src/android/libs/devicex-bridge.aar`: Bridge Kotlin con API Cordova
|
|
431
|
+
- `src/android/libs/devicex-1.1.3.aar`: SDK Device Intelligence empaquetado
|
|
432
|
+
- `www/devicex.js`: Interfaz JavaScript
|
|
433
|
+
- `types/index.d.ts`: Definiciones TypeScript
|
|
434
|
+
- Dependencias: `kotlin-stdlib:1.9.25`, `kotlinx-coroutines-android:1.7.3`
|
|
435
|
+
|
|
436
|
+
### Reconstruir AARs (solo mantenedores)
|
|
437
|
+
|
|
438
|
+
**Compilar SDK:**
|
|
439
|
+
```bash
|
|
440
|
+
cd device-intelligence-android
|
|
441
|
+
export JAVA_HOME="$(/usr/libexec/java_home -v 11)"
|
|
442
|
+
./gradlew :devicex:clean :devicex:assembleProdEnvRelease
|
|
443
|
+
./gradlew :devicex:publishAgentProductionReleasePublicationToMavenLocal
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**Compilar bridge:**
|
|
447
|
+
```bash
|
|
448
|
+
cd devicex-bridge-android
|
|
449
|
+
export JAVA_HOME="$(/usr/libexec/java_home -v 11)"
|
|
450
|
+
./gradlew :bridge:clean :bridge:assembleRelease
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**Copiar AARs al plugin:**
|
|
454
|
+
```bash
|
|
455
|
+
cp devicex-bridge-android/bridge/build/outputs/aar/devicex-bridge.aar \
|
|
456
|
+
cordova-plugin-devicex/src/android/libs/
|
|
457
|
+
|
|
458
|
+
cp ~/.m2/repository/com/gatekeeperx/devicex/1.1.6/devicex-1.1.3.aar \
|
|
459
|
+
cordova-plugin-devicex/src/android/libs/
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Publicar a npm
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
# Actualizar versión
|
|
466
|
+
npm version patch # o minor/major
|
|
467
|
+
|
|
468
|
+
# Publicar
|
|
469
|
+
npm publish --access public
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## Licencia
|
|
475
|
+
|
|
476
|
+
Apache-2.0
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## Soporte
|
|
481
|
+
|
|
482
|
+
- **Documentación:** [https://docs.gatekeeperx.com](https://docs.gatekeeperx.com)
|
|
483
|
+
- **Issues:** [GitHub Issues](https://github.com/gatekeeperx/cordova-plugin-devicex/issues)
|
|
484
|
+
- **npm:** [cordova-plugin-devicex](https://www.npmjs.com/package/cordova-plugin-devicex)
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gatekeeperx/cordova-plugin-devicex",
|
|
3
|
+
"version": "1.2.5",
|
|
4
|
+
"description": "GatekeeperX Device Intelligence Cordova plugin (Android)",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"cordova",
|
|
8
|
+
"cordova-android",
|
|
9
|
+
"gatekeeperx",
|
|
10
|
+
"device",
|
|
11
|
+
"security",
|
|
12
|
+
"intelligence"
|
|
13
|
+
],
|
|
14
|
+
"engines": [
|
|
15
|
+
{
|
|
16
|
+
"name": "cordova-android",
|
|
17
|
+
"version": ">=11.0.0"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"cordova": {
|
|
21
|
+
"id": "cordova-plugin-devicex",
|
|
22
|
+
"platforms": [
|
|
23
|
+
"android"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"main": "www/devicex.js",
|
|
27
|
+
"types": "types/index.d.ts",
|
|
28
|
+
"files": [
|
|
29
|
+
"plugin.xml",
|
|
30
|
+
"www/",
|
|
31
|
+
"types/",
|
|
32
|
+
"src/android/",
|
|
33
|
+
"README.md",
|
|
34
|
+
"CHANGELOG.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/gatekeeperx/deviceX-plugins.git"
|
|
40
|
+
},
|
|
41
|
+
"author": "GatekeeperX",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/gatekeeperx/deviceX-plugins/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://github.com/gatekeeperx/deviceX-plugins/tree/master/cordova/cordova-plugin-devicex"
|
|
46
|
+
}
|
package/plugin.xml
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<plugin id="@gatekeeperx/cordova-plugin-devicex"
|
|
3
|
+
xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
|
4
|
+
xmlns:android="http://schemas.android.com/apk/res/android" version="1.2.1">
|
|
5
|
+
<name>Devicex</name>
|
|
6
|
+
<description>GatekeeperX Device Intelligence Cordova plugin (Android)</description>
|
|
7
|
+
<license>Apache-2.0</license>
|
|
8
|
+
<keywords>cordova, gatekeeperx, device, intelligence, security</keywords>
|
|
9
|
+
|
|
10
|
+
<js-module name="Devicex" src="www/devicex.js">
|
|
11
|
+
<clobbers target="DeviceX" />
|
|
12
|
+
</js-module>
|
|
13
|
+
|
|
14
|
+
<engines>
|
|
15
|
+
<engine name="cordova-android" version=">=11.0.0" />
|
|
16
|
+
</engines>
|
|
17
|
+
|
|
18
|
+
<platform name="android">
|
|
19
|
+
<!-- Runtime dependencies -->
|
|
20
|
+
<!-- Kotlin stdlib alineado con el bridge -->
|
|
21
|
+
<framework src="org.jetbrains.kotlin:kotlin-stdlib:1.9.25" />
|
|
22
|
+
<framework src="org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3" />
|
|
23
|
+
|
|
24
|
+
<!-- Kotlinx Serialization (requerido por Ktor) -->
|
|
25
|
+
<framework src="org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2" />
|
|
26
|
+
|
|
27
|
+
<!-- Ktor Client (HTTP engine del SDK) -->
|
|
28
|
+
<framework src="io.ktor:ktor-client-cio:2.3.7" />
|
|
29
|
+
<framework src="io.ktor:ktor-client-logging:2.3.7" />
|
|
30
|
+
<framework src="io.ktor:ktor-client-content-negotiation:2.3.7" />
|
|
31
|
+
<framework src="io.ktor:ktor-serialization-kotlinx-json:2.3.7" />
|
|
32
|
+
<!-- AARs locales -->
|
|
33
|
+
<lib-file src="src/android/libs/devicex-bridge.aar" arch="device" />
|
|
34
|
+
<lib-file src="src/android/libs/devicex-1.2.5.aar" arch="device" />
|
|
35
|
+
|
|
36
|
+
<!-- Hook para configurar Gradle -->
|
|
37
|
+
<hook type="after_plugin_install" src="src/android/hooks/configure-gradle.js" />
|
|
38
|
+
|
|
39
|
+
<!-- Registrar el plugin nativo en config.xml -->
|
|
40
|
+
<config-file target="res/xml/config.xml" parent="/*">
|
|
41
|
+
<feature name="Devicex">
|
|
42
|
+
<param name="android-package" value="com.gatekeeperx.cordova.DevicexPlugin" />
|
|
43
|
+
<param name="onload" value="true" />
|
|
44
|
+
</feature>
|
|
45
|
+
</config-file>
|
|
46
|
+
|
|
47
|
+
<!-- Incluir la clase Java del plugin -->
|
|
48
|
+
<source-file src="src/android/com/gatekeeperx/cordova/DevicexPlugin.java" target-dir="src/com/gatekeeperx/cordova" />
|
|
49
|
+
</platform>
|
|
50
|
+
</plugin>
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
package com.gatekeeperx.cordova;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
|
|
5
|
+
import org.apache.cordova.CallbackContext;
|
|
6
|
+
import org.apache.cordova.CordovaInterface;
|
|
7
|
+
import org.apache.cordova.CordovaPlugin;
|
|
8
|
+
import org.apache.cordova.CordovaWebView;
|
|
9
|
+
import org.json.JSONArray;
|
|
10
|
+
import org.json.JSONException;
|
|
11
|
+
import org.json.JSONObject;
|
|
12
|
+
|
|
13
|
+
import java.util.ArrayList;
|
|
14
|
+
import java.util.HashMap;
|
|
15
|
+
import java.util.Iterator;
|
|
16
|
+
import java.util.List;
|
|
17
|
+
import java.util.Map;
|
|
18
|
+
|
|
19
|
+
public class DevicexPlugin extends CordovaPlugin {
|
|
20
|
+
|
|
21
|
+
@Override
|
|
22
|
+
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
|
|
23
|
+
super.initialize(cordova, webView);
|
|
24
|
+
try {
|
|
25
|
+
Context ctx = cordova.getActivity().getApplicationContext();
|
|
26
|
+
android.util.Log.d("DevicexPlugin", "Reading meta-data from manifest...");
|
|
27
|
+
|
|
28
|
+
android.content.pm.ApplicationInfo ai = ctx.getPackageManager()
|
|
29
|
+
.getApplicationInfo(ctx.getPackageName(), android.content.pm.PackageManager.GET_META_DATA);
|
|
30
|
+
android.os.Bundle meta = ai.metaData;
|
|
31
|
+
|
|
32
|
+
if (meta == null) {
|
|
33
|
+
android.util.Log.e("DevicexPlugin", "No meta-data found in manifest");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
String tenant = meta.getString("com.gatekeeperx.deviceintelligence.TENANT");
|
|
38
|
+
String apiKey = meta.getString("com.gatekeeperx.deviceintelligence.API_KEY");
|
|
39
|
+
String env = meta.getString("com.gatekeeperx.deviceintelligence.ENVIRONMENT");
|
|
40
|
+
String orgId = meta.getString("com.gatekeeperx.deviceintelligence.ORGANIZATION_ID");
|
|
41
|
+
|
|
42
|
+
android.util.Log.d("DevicexPlugin", "Tenant: " + tenant + ", Env: " + env);
|
|
43
|
+
|
|
44
|
+
if (tenant == null || tenant.trim().isEmpty() || apiKey == null || apiKey.trim().isEmpty()) {
|
|
45
|
+
android.util.Log.d("DevicexPlugin", "Auto-config skipped: no credentials provided");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
boolean ok = DevicexBridge.INSTANCE.configure(
|
|
50
|
+
ctx,
|
|
51
|
+
tenant.trim(),
|
|
52
|
+
apiKey.trim(),
|
|
53
|
+
env != null ? env.trim() : "PRODUCTION",
|
|
54
|
+
orgId != null ? orgId.trim() : null,
|
|
55
|
+
null);
|
|
56
|
+
|
|
57
|
+
android.util.Log.d("DevicexPlugin", "Manual configure result: " + ok);
|
|
58
|
+
} catch (Throwable e) {
|
|
59
|
+
android.util.Log.e("DevicexPlugin", "Error initializing: " + e.getMessage(), e);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@Override
|
|
64
|
+
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
|
|
65
|
+
switch (action) {
|
|
66
|
+
case "configure":
|
|
67
|
+
configure(args, callbackContext);
|
|
68
|
+
return true;
|
|
69
|
+
case "sendEvent":
|
|
70
|
+
sendEvent(args, callbackContext);
|
|
71
|
+
return true;
|
|
72
|
+
case "isInitialized":
|
|
73
|
+
try {
|
|
74
|
+
boolean value = DevicexBridge.INSTANCE.isInitialized();
|
|
75
|
+
callbackContext.success(new JSONObject().put("value", value));
|
|
76
|
+
} catch (JSONException e) {
|
|
77
|
+
callbackContext.error(e.getMessage());
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
case "getVersion":
|
|
81
|
+
try {
|
|
82
|
+
String value = DevicexBridge.INSTANCE.getVersion();
|
|
83
|
+
callbackContext.success(new JSONObject().put("value", value));
|
|
84
|
+
} catch (JSONException e) {
|
|
85
|
+
callbackContext.error(e.getMessage());
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
default:
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private void configure(JSONArray args, CallbackContext cb) {
|
|
94
|
+
try {
|
|
95
|
+
JSONObject obj = args.optJSONObject(0);
|
|
96
|
+
if (obj == null)
|
|
97
|
+
obj = new JSONObject();
|
|
98
|
+
Context ctx = cordova.getActivity().getApplicationContext();
|
|
99
|
+
String tenant = obj.optString("tenant", "").trim();
|
|
100
|
+
String apiKey = obj.optString("apiKey", "").trim();
|
|
101
|
+
String orgId = obj.optString("organizationId", "").trim();
|
|
102
|
+
String env = obj.optString("environment", "PRODUCTION").trim();
|
|
103
|
+
JSONObject headersObj = obj.optJSONObject("headers");
|
|
104
|
+
Map<String, String> headers = headersObj != null ? toStringMap(headersObj) : new HashMap<>();
|
|
105
|
+
|
|
106
|
+
if (tenant.isEmpty() || apiKey.isEmpty()) {
|
|
107
|
+
cb.error("tenant and apiKey are required");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
boolean ok = DevicexBridge.INSTANCE.configure(
|
|
112
|
+
ctx,
|
|
113
|
+
tenant,
|
|
114
|
+
apiKey,
|
|
115
|
+
env,
|
|
116
|
+
orgId.isEmpty() ? null : orgId,
|
|
117
|
+
headers);
|
|
118
|
+
if (ok)
|
|
119
|
+
cb.success();
|
|
120
|
+
else
|
|
121
|
+
cb.error("configure failed");
|
|
122
|
+
} catch (Throwable e) {
|
|
123
|
+
cb.error(e.getMessage());
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private void sendEvent(JSONArray args, final CallbackContext cb) {
|
|
128
|
+
try {
|
|
129
|
+
JSONObject obj = args.optJSONObject(0);
|
|
130
|
+
if (obj == null)
|
|
131
|
+
obj = new JSONObject();
|
|
132
|
+
String name = obj.optString("name", "").trim();
|
|
133
|
+
if (name.isEmpty()) {
|
|
134
|
+
cb.error("name is required");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
JSONObject propsObj = obj.optJSONObject("properties");
|
|
138
|
+
JSONObject headersObj = obj.optJSONObject("headers");
|
|
139
|
+
Map<String, Object> properties = propsObj != null ? toAnyMap(propsObj) : new HashMap<String, Object>();
|
|
140
|
+
Map<String, String> headers = headersObj != null ? toStringMap(headersObj) : new HashMap<String, String>();
|
|
141
|
+
|
|
142
|
+
@SuppressWarnings("unchecked")
|
|
143
|
+
DevicexBridge.EventCallback callback = new DevicexBridge.EventCallback() {
|
|
144
|
+
@Override
|
|
145
|
+
public void onResult(Map result) {
|
|
146
|
+
try {
|
|
147
|
+
cb.success(new JSONObject(result));
|
|
148
|
+
} catch (Throwable t) {
|
|
149
|
+
cb.error(t.getMessage());
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
DevicexBridge.INSTANCE.sendEvent(name, properties, headers, callback);
|
|
154
|
+
} catch (Throwable e) {
|
|
155
|
+
cb.error(e.getMessage());
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Helpers
|
|
160
|
+
private static Map<String, String> toStringMap(JSONObject obj) {
|
|
161
|
+
Map<String, String> map = new HashMap<>();
|
|
162
|
+
Iterator<String> it = obj.keys();
|
|
163
|
+
while (it.hasNext()) {
|
|
164
|
+
String k = it.next();
|
|
165
|
+
String v = obj.optString(k, null);
|
|
166
|
+
if (v != null)
|
|
167
|
+
map.put(k, v);
|
|
168
|
+
}
|
|
169
|
+
return map;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private static Map<String, Object> toAnyMap(JSONObject obj) {
|
|
173
|
+
Map<String, Object> map = new HashMap<>();
|
|
174
|
+
Iterator<String> it = obj.keys();
|
|
175
|
+
while (it.hasNext()) {
|
|
176
|
+
String k = it.next();
|
|
177
|
+
Object v = obj.opt(k);
|
|
178
|
+
map.put(k, fromJson(v));
|
|
179
|
+
}
|
|
180
|
+
return map;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private static Object fromJson(Object v) {
|
|
184
|
+
if (v == null || v == JSONObject.NULL)
|
|
185
|
+
return null;
|
|
186
|
+
if (v instanceof JSONObject)
|
|
187
|
+
return toAnyMap((JSONObject) v);
|
|
188
|
+
if (v instanceof JSONArray)
|
|
189
|
+
return toList((JSONArray) v);
|
|
190
|
+
if (v instanceof String || v instanceof Boolean || v instanceof Integer || v instanceof Long
|
|
191
|
+
|| v instanceof Double)
|
|
192
|
+
return v;
|
|
193
|
+
return String.valueOf(v);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private static List<Object> toList(JSONArray arr) {
|
|
197
|
+
List<Object> list = new ArrayList<>();
|
|
198
|
+
for (int i = 0; i < arr.length(); i++) {
|
|
199
|
+
Object v = arr.opt(i);
|
|
200
|
+
list.add(fromJson(v));
|
|
201
|
+
}
|
|
202
|
+
return list;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
module.exports = function (context) {
|
|
7
|
+
const platforms = context.opts.cordova.platforms;
|
|
8
|
+
if (platforms.indexOf('android') === -1) return;
|
|
9
|
+
|
|
10
|
+
const buildGradlePath = path.join(
|
|
11
|
+
context.opts.projectRoot,
|
|
12
|
+
'platforms',
|
|
13
|
+
'android',
|
|
14
|
+
'app',
|
|
15
|
+
'build.gradle'
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
if (!fs.existsSync(buildGradlePath)) {
|
|
19
|
+
console.log('[devicex] build.gradle no encontrado');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let buildGradle = fs.readFileSync(buildGradlePath, 'utf8');
|
|
24
|
+
|
|
25
|
+
// Agregar repositorio flatDir si no existe en el bloque principal
|
|
26
|
+
if (buildGradle.indexOf('flatDir') === -1) {
|
|
27
|
+
const repoBlock = `
|
|
28
|
+
repositories {
|
|
29
|
+
flatDir {
|
|
30
|
+
dirs 'libs'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
// Insertar antes del último bloque dependencies (el principal)
|
|
35
|
+
const lastDepsIndex = buildGradle.lastIndexOf('dependencies {');
|
|
36
|
+
if (lastDepsIndex !== -1) {
|
|
37
|
+
buildGradle = buildGradle.slice(0, lastDepsIndex) +
|
|
38
|
+
repoBlock + '\n' +
|
|
39
|
+
buildGradle.slice(lastDepsIndex);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Agregar dependencias de AARs después de fileTree si no existen
|
|
44
|
+
if (buildGradle.indexOf('devicex-bridge') === -1) {
|
|
45
|
+
const depsBlock = ` implementation files('libs/devicex-bridge.aar')
|
|
46
|
+
implementation files('libs/devicex-1.2.5.aar')
|
|
47
|
+
|
|
48
|
+
// Dependencias del SDK Devicex
|
|
49
|
+
implementation 'io.ktor:ktor-client-core:2.3.7'
|
|
50
|
+
implementation 'io.ktor:ktor-client-okhttp:2.3.7'
|
|
51
|
+
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2'
|
|
52
|
+
`;
|
|
53
|
+
// Buscar después de fileTree en el bloque principal
|
|
54
|
+
buildGradle = buildGradle.replace(
|
|
55
|
+
/(implementation fileTree\(dir: 'libs', include: '\*\.jar'\))/,
|
|
56
|
+
'$1\n' + depsBlock
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
fs.writeFileSync(buildGradlePath, buildGradle, 'utf8');
|
|
61
|
+
console.log('[devicex] build.gradle configurado con AARs locales');
|
|
62
|
+
};
|
|
Binary file
|
|
Binary file
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Type definitions for cordova-plugin-devicex
|
|
2
|
+
// Project: https://npmjs.com/package/cordova-plugin-devicex
|
|
3
|
+
// Definitions by: GatekeeperX
|
|
4
|
+
|
|
5
|
+
export type Environment = 'DEV' | 'DEVELOPMENT' | 'SANDBOX' | 'STAGE' | 'STAGING' | 'PROD' | 'PRODUCTION';
|
|
6
|
+
|
|
7
|
+
export interface ConfigureOptions {
|
|
8
|
+
tenant: string;
|
|
9
|
+
apiKey: string;
|
|
10
|
+
organizationId?: string;
|
|
11
|
+
environment?: Environment;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface EventSuccess {
|
|
16
|
+
ok: true;
|
|
17
|
+
code: number;
|
|
18
|
+
deviceXId: string;
|
|
19
|
+
message?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface EventFailure {
|
|
23
|
+
ok: false;
|
|
24
|
+
errorCode: string;
|
|
25
|
+
errorMessage: string;
|
|
26
|
+
httpCode?: number | null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type EventResult = EventSuccess | EventFailure;
|
|
30
|
+
|
|
31
|
+
export interface RiskAssessment {
|
|
32
|
+
isRooted: boolean;
|
|
33
|
+
isFridaDetected: boolean;
|
|
34
|
+
isXposedDetected: boolean;
|
|
35
|
+
isMagiskDetected: boolean;
|
|
36
|
+
isEmulator: boolean;
|
|
37
|
+
isDebuggerAttached: boolean;
|
|
38
|
+
isHookingDetected: boolean;
|
|
39
|
+
riskScore: number;
|
|
40
|
+
riskLevel: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare const Devicex: {
|
|
44
|
+
configure(options: ConfigureOptions): Promise<void>;
|
|
45
|
+
sendEvent(name: string, properties?: Record<string, any>, headers?: Record<string, string>): Promise<EventResult>;
|
|
46
|
+
getRiskAssessment(): Promise<RiskAssessment>;
|
|
47
|
+
isInitialized(): Promise<boolean>;
|
|
48
|
+
getVersion(): Promise<string>;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default Devicex;
|
|
52
|
+
export as namespace Devicex;
|
package/www/devicex.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var exec = require('cordova/exec');
|
|
2
|
+
var PLUGIN = 'Devicex';
|
|
3
|
+
|
|
4
|
+
function call(action, args) {
|
|
5
|
+
return new Promise(function (resolve, reject) {
|
|
6
|
+
exec(function (res) { resolve(res); }, function (err) { reject(err); }, PLUGIN, action, args || []);
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
exports.configure = function (options) {
|
|
11
|
+
options = options || {};
|
|
12
|
+
return call('configure', [options]);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
exports.sendEvent = function (name, properties, headers) {
|
|
16
|
+
if (!name || typeof name !== 'string') {
|
|
17
|
+
return Promise.reject('name is required');
|
|
18
|
+
}
|
|
19
|
+
return call('sendEvent', [{ name: name, properties: properties || {}, headers: headers || {} }]);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
exports.isInitialized = function () {
|
|
23
|
+
return call('isInitialized', []).then(function (res) { return res && res.value === true; });
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
exports.getVersion = function () {
|
|
27
|
+
return call('getVersion', []).then(function (res) { return (res && res.value) || ''; });
|
|
28
|
+
};
|