expo-gliph-player 1.0.0

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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +348 -0
  3. package/android/build.gradle +82 -0
  4. package/android/src/main/AndroidManifest.xml +31 -0
  5. package/android/src/main/java/com/gliphplayer/DeviceInfoModule.kt +48 -0
  6. package/android/src/main/java/com/gliphplayer/DeviceInfoPackage.kt +16 -0
  7. package/android/src/main/java/com/gliphplayer/GliphPlayerModule.kt +360 -0
  8. package/android/src/main/java/com/gliphplayer/GliphPlayerPackage.kt +48 -0
  9. package/android/src/main/java/com/gliphplayer/GliphPlayerService.kt +797 -0
  10. package/android/src/main/res/xml/automotive_app_desc.xml +4 -0
  11. package/android/src/oldarch/com/gliphplayer/NativeGliphPlayerSpec.kt +56 -0
  12. package/app.plugin.js +1 -0
  13. package/expo-gliph-player.podspec +91 -0
  14. package/ios/GliphAudioPlayer.h +77 -0
  15. package/ios/GliphAudioPlayer.swift +697 -0
  16. package/ios/GliphPlayer-Bridging-Header.h +3 -0
  17. package/ios/GliphPlayerModule.h +12 -0
  18. package/ios/GliphPlayerModule.mm +243 -0
  19. package/ios/expo_gliph_player.h +22 -0
  20. package/lib/commonjs/GliphPlayer.js +310 -0
  21. package/lib/commonjs/GliphPlayer.js.map +1 -0
  22. package/lib/commonjs/hooks.js +233 -0
  23. package/lib/commonjs/hooks.js.map +1 -0
  24. package/lib/commonjs/index.js +166 -0
  25. package/lib/commonjs/index.js.map +1 -0
  26. package/lib/commonjs/package.json +1 -0
  27. package/lib/commonjs/specs/NativeGliphPlayer.js +19 -0
  28. package/lib/commonjs/specs/NativeGliphPlayer.js.map +1 -0
  29. package/lib/commonjs/types.js +175 -0
  30. package/lib/commonjs/types.js.map +1 -0
  31. package/lib/module/GliphPlayer.js +305 -0
  32. package/lib/module/GliphPlayer.js.map +1 -0
  33. package/lib/module/hooks.js +221 -0
  34. package/lib/module/hooks.js.map +1 -0
  35. package/lib/module/index.js +20 -0
  36. package/lib/module/index.js.map +1 -0
  37. package/lib/module/package.json +1 -0
  38. package/lib/module/specs/NativeGliphPlayer.js +20 -0
  39. package/lib/module/specs/NativeGliphPlayer.js.map +1 -0
  40. package/lib/module/types.js +181 -0
  41. package/lib/module/types.js.map +1 -0
  42. package/lib/typescript/src/GliphPlayer.d.ts +113 -0
  43. package/lib/typescript/src/GliphPlayer.d.ts.map +1 -0
  44. package/lib/typescript/src/hooks.d.ts +51 -0
  45. package/lib/typescript/src/hooks.d.ts.map +1 -0
  46. package/lib/typescript/src/index.d.ts +11 -0
  47. package/lib/typescript/src/index.d.ts.map +1 -0
  48. package/lib/typescript/src/specs/NativeGliphPlayer.d.ts +80 -0
  49. package/lib/typescript/src/specs/NativeGliphPlayer.d.ts.map +1 -0
  50. package/lib/typescript/src/types.d.ts +348 -0
  51. package/lib/typescript/src/types.d.ts.map +1 -0
  52. package/package.json +62 -0
  53. package/src/GliphPlayer.ts +356 -0
  54. package/src/hooks.ts +256 -0
  55. package/src/index.ts +61 -0
  56. package/src/specs/NativeGliphPlayer.ts +105 -0
  57. package/src/types.ts +395 -0
  58. package/src/withGliphPlayer.js +166 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 react-native-gliph-player contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,348 @@
1
+ # 🎵 expo-gliph-player
2
+
3
+ [![npm version](https://shields.io)](https://npmjs.com)
4
+ [![License: MIT](https://shields.io)](https://opensource.org)
5
+
6
+ **Fixed version of react-native-gliph-player with full Expo compatibility.** All iOS bridge fixes, Swift/Objective-C issues, and Android `autoSkipOnError` patches are pre-applied.
7
+
8
+ ---
9
+
10
+ ## 📦 Installation
11
+
12
+ ```bash
13
+ npm install expo-gliph-player
14
+ # or
15
+ yarn add expo-gliph-player
16
+ ```
17
+
18
+ ### From GitHub (Alternative):
19
+
20
+ ```bash
21
+ yarn add https://github.com
22
+ ```
23
+
24
+ ---
25
+
26
+ ## 🚀 Setup & Configuration
27
+
28
+ ### 1. Configure `app.json`
29
+
30
+ Since this package contains native code, you must add the config plugin and configure background capabilities for iOS and Android:
31
+
32
+ ```json
33
+ {
34
+ "expo": {
35
+ "plugins": ["expo-gliph-player"],
36
+ "ios": {
37
+ "infoPlist": {
38
+ "UIBackgroundModes": ["audio"]
39
+ }
40
+ },
41
+ "android": {
42
+ "permissions": ["android.permission.FOREGROUND_SERVICE"]
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ ### 2. Build the App
49
+
50
+ This package uses native code. Run prebuild before launching the project:
51
+
52
+ ```bash
53
+ npx expo prebuild
54
+ # then run on device/emulator
55
+ npx expo run:ios
56
+ # or
57
+ npx expo run:android
58
+ ```
59
+
60
+ ---
61
+
62
+ ## 💻 Reactive State
63
+
64
+ Instead of manually fetching state, Gliph Player ships with powerful React Hooks. These hooks automatically re-render your components whenever the audio state changes.
65
+
66
+ ### Play/Pause State:
67
+
68
+ ```tsx
69
+ import { useIsPlaying } from 'expo-gliph-player';
70
+
71
+ const { playing } = useIsPlaying(); // Returns true or false
72
+ ```
73
+
74
+ ### Progress & Duration (in seconds):
75
+
76
+ ```tsx
77
+ import { useProgress } from 'expo-gliph-player';
78
+
79
+ const { position, duration } = useProgress(500); // Updates every 500ms
80
+ ```
81
+
82
+ ### "Now Playing" Track Metadata:
83
+
84
+ ```tsx
85
+ import { useActiveTrack } from 'expo-gliph-player';
86
+
87
+ const track = useActiveTrack(); // Contains url, title, artist, artwork
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 🎛️ Playback & Queue Controls
93
+
94
+ ### Basic Controls
95
+
96
+ ```tsx
97
+ await GliphPlayer.play();
98
+ await GliphPlayer.pause();
99
+ await GliphPlayer.stop();
100
+ ```
101
+
102
+ ### Navigation & Seeking
103
+
104
+ ```tsx
105
+ await GliphPlayer.skipToNext();
106
+ await GliphPlayer.skipToPrevious();
107
+ await GliphPlayer.seekTo(60); // Jump to exactly 1 minute (in seconds)
108
+ await GliphPlayer.seekBy(15); // Jump forward 15 seconds (great for podcasts)
109
+ ```
110
+
111
+ ### Managing the Queue
112
+
113
+ You can dynamically add, remove, or reorder tracks while the audio is playing.
114
+
115
+ ```tsx
116
+ // Add a track to the end of the queue
117
+ await GliphPlayer.add({
118
+ id: 'new-song',
119
+ url: 'https://example.com',
120
+ title: 'Just Added',
121
+ artist: 'User'
122
+ });
123
+
124
+ // Remove a specific track by ID
125
+ await GliphPlayer.remove('track-1');
126
+
127
+ // Stop playback and empty the queue entirely
128
+ await GliphPlayer.reset();
129
+ ```
130
+
131
+ ---
132
+
133
+ ## 🔒 Lock Screen & Background Events
134
+
135
+ To ensure your lock screen and notification panel controls actually respond to user input, you must connect native remote events to the player engine.
136
+
137
+ ### Inside Components (`useTrackPlayerEvents`)
138
+
139
+ ```tsx
140
+ import { useTrackPlayerEvents, Event } from 'expo-gliph-player';
141
+ import GliphPlayer from 'expo-gliph-player';
142
+
143
+ export function PlaybackObserver() {
144
+ useTrackPlayerEvents([
145
+ Event.RemotePlay,
146
+ Event.RemotePause,
147
+ Event.RemoteNext,
148
+ Event.RemotePrevious
149
+ ], (event) => {
150
+ if (event.type === Event.RemotePlay) GliphPlayer.play();
151
+ if (event.type === Event.RemotePause) GliphPlayer.pause();
152
+ if (event.type === Event.RemoteNext) GliphPlayer.skipToNext();
153
+ if (event.type === Event.RemotePrevious) GliphPlayer.skipToPrevious();
154
+ });
155
+
156
+ return null; // Headless component, acts as a layout listener
157
+ }
158
+ ```
159
+
160
+ ### Global Listeners (`GliphPlayer.addEventListener`)
161
+
162
+ To handle audio events even when your React UI components are unmounted, register global listeners inside your app root (`index.js` or `App.tsx` outside the component lifecycle):
163
+
164
+ ```tsx
165
+ import GliphPlayer, { Event } from 'expo-gliph-player';
166
+
167
+ GliphPlayer.addEventListener(Event.RemotePlay, () => {
168
+ GliphPlayer.play();
169
+ });
170
+
171
+ GliphPlayer.addEventListener(Event.RemotePause, () => {
172
+ GliphPlayer.pause();
173
+ });
174
+ ```
175
+
176
+ ---
177
+
178
+ ## 🚀 Full Implementation Example
179
+
180
+ Here is a production-ready, complete example split into the main entry file (`App.tsx`) and the user interface component (`MusicPlayer.tsx`).
181
+
182
+ ### 1. App.tsx (Main Entry & Background Engine Setup)
183
+
184
+ ```tsx
185
+ import React, { useEffect } from 'react';
186
+ import { View, Platform, PermissionsAndroid } from 'react-native';
187
+ import GliphPlayer, { Capability, AppKilledPlaybackBehavior } from 'expo-gliph-player';
188
+ import { MusicPlayer } from './components/MusicPlayer';
189
+
190
+ const tracks = [
191
+ {
192
+ id: '1',
193
+ url: 'https://example.com',
194
+ title: 'Gliph Journey',
195
+ artist: 'Gliph Labs',
196
+ artwork: 'https://example.com',
197
+ },
198
+ ];
199
+
200
+ export default function App() {
201
+ useEffect(() => {
202
+ const setup = async () => {
203
+ // 1. Android Notification Permission (API 33+)
204
+ if (Platform.OS === 'android' && Platform.Version >= 33) {
205
+ await PermissionsAndroid.request('android.permission.POST_NOTIFICATIONS' as any);
206
+ }
207
+
208
+ // 2. Setup the engine
209
+ await GliphPlayer.setupPlayer({
210
+ playBuffer: 0.5, // 0.5s buffer for zero-lag seeking
211
+ android: {
212
+ appKilledPlaybackBehavior: AppKilledPlaybackBehavior.ContinuePlayback,
213
+ },
214
+ });
215
+
216
+ // 3. Define Lock Screen / Notification Controls
217
+ await GliphPlayer.updateOptions({
218
+ capabilities: [
219
+ Capability.Play, Capability.Pause,
220
+ Capability.SkipToNext, Capability.SkipToPrevious,
221
+ Capability.SeekTo,
222
+ ],
223
+ });
224
+
225
+ // 4. Add tracks to queue
226
+ await GliphPlayer.add(tracks);
227
+ };
228
+
229
+ setup();
230
+ }, []);
231
+
232
+ return (
233
+ <View style={{ flex: 1, backgroundColor: '#121212' }}>
234
+ <MusicPlayer />
235
+ </View>
236
+ );
237
+ }
238
+ ```
239
+
240
+ ### 2. MusicPlayer.tsx (UI Component)
241
+
242
+ ```tsx
243
+ import React, { useState } from 'react';
244
+ import { View, Text, TouchableOpacity, Image, StyleSheet } from 'react-native';
245
+ import Slider from '@react-native-community/slider';
246
+ import GliphPlayer, { useIsPlaying, useProgress, useActiveTrack, RepeatMode } from 'expo-gliph-player';
247
+
248
+ export const MusicPlayer = () => {
249
+ const { playing } = useIsPlaying();
250
+ const { position, duration } = useProgress(500);
251
+ const track = useActiveTrack();
252
+ const [repeatMode, setRepeatMode] = useState('off');
253
+
254
+ const togglePlayback = async () => {
255
+ if (playing) {
256
+ await GliphPlayer.pause();
257
+ } else {
258
+ await GliphPlayer.play();
259
+ }
260
+ };
261
+
262
+ const cycleRepeat = async () => {
263
+ const next = repeatMode === 'off' ? 'one' : repeatMode === 'one' ? 'all' : 'off';
264
+ setRepeatMode(next);
265
+ await GliphPlayer.setRepeatMode(
266
+ next === 'one' ? RepeatMode.Track : next === 'all' ? RepeatMode.Queue : RepeatMode.Off
267
+ );
268
+ };
269
+
270
+ return (
271
+ <View style={styles.container}>
272
+ <Image source={{ uri: track?.artwork }} style={styles.artwork} />
273
+ <Text style={styles.title}>{track?.title || 'No Track'}</Text>
274
+
275
+ <Slider
276
+ style={{ width: '100%', height: 40 }}
277
+ value={position}
278
+ maximumValue={duration || 1}
279
+ onSlidingComplete={(val) => GliphPlayer.seekTo(val)}
280
+ minimumTrackTintColor="#1DB954"
281
+ />
282
+
283
+ <View style={styles.controls}>
284
+ <TouchableOpacity onPress={() => GliphPlayer.skipToPrevious()}>
285
+ <Text style={styles.btn}>Prev</Text>
286
+ </TouchableOpacity>
287
+
288
+ <TouchableOpacity onPress={togglePlayback} style={styles.playBtn}>
289
+ <Text style={{ color: '#fff' }}>{playing ? 'PAUSE' : 'PLAY'}</Text>
290
+ </TouchableOpacity>
291
+
292
+ <TouchableOpacity onPress={() => GliphPlayer.skipToNext()}>
293
+ <Text style={styles.btn}>Next</Text>
294
+ </TouchableOpacity>
295
+ </View>
296
+
297
+ <TouchableOpacity onPress={cycleRepeat} style={{ marginTop: 20 }}>
298
+ <Text style={{ color: '#1DB954' }}>Repeat: {repeatMode.toUpperCase()}</Text>
299
+ </TouchableOpacity>
300
+ </View>
301
+ );
302
+ };
303
+
304
+ const styles = StyleSheet.create({
305
+ container: { padding: 20, alignItems: 'center', justifyContent: 'center', flex: 1 },
306
+ artwork: { width: 300, height: 300, borderRadius: 10 },
307
+ title: { color: '#fff', fontSize: 24, marginVertical: 20 },
308
+ controls: { flexDirection: 'row', alignItems: 'center', gap: 40, marginTop: 20 },
309
+ playBtn: { width: 80, height: 80, borderRadius: 40, backgroundColor: '#333', justifyContent: 'center', alignItems: 'center' },
310
+ btn: { color: '#fff', fontSize: 18 }
311
+ });
312
+ ```
313
+
314
+ ---
315
+
316
+ ## 🔧 What's Fixed
317
+
318
+ ### iOS:
319
+ - ✅ Fixed Swift/Objective-C bridging with `GliphAudioPlayer.h`.
320
+ - ✅ Removed ReactCodegen dependency (no more build errors).
321
+ - ✅ Fixed `use_frameworks!` compatibility.
322
+ - ✅ Correct Swift module generation.
323
+
324
+ ### Android:
325
+ - ✅ Fixed `autoSkipOnError` crash (`NoSuchKeyException`).
326
+ - ✅ Proper foreground service registration.
327
+ - ✅ `MainApplication.kt` autolinking.
328
+
329
+ ---
330
+
331
+ ## 📋 Requirements
332
+
333
+ - **Expo SDK:** 50+
334
+ - **React Native:** 0.71+
335
+ - **iOS:** 14.0+
336
+ - **Android:** API 21+
337
+
338
+ ---
339
+
340
+ ## 📄 License
341
+
342
+ MIT
343
+
344
+ ---
345
+
346
+ ## 🙏 Credits
347
+
348
+ Based on [react-native-gliph-player](https://github.com) by Gliph Labs.
@@ -0,0 +1,82 @@
1
+ buildscript {
2
+ repositories {
3
+ google()
4
+ mavenCentral()
5
+ }
6
+ dependencies {
7
+ classpath "com.android.tools.build:gradle:8.1.0"
8
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0"
9
+ }
10
+ }
11
+
12
+ // ─── Fix #1: Apply the React Native Gradle plugin FIRST ──────────────────────
13
+ // This is required for Codegen to run and generate the TurboModule C++/Java
14
+ // bindings. Without it, JSI linking fails silently on New Architecture.
15
+ apply plugin: 'com.android.library'
16
+ apply plugin: 'kotlin-android'
17
+ apply plugin: 'com.facebook.react'
18
+
19
+ android {
20
+ compileSdkVersion 36
21
+ namespace "com.gliphplayer"
22
+
23
+ defaultConfig {
24
+ minSdkVersion 24
25
+ targetSdkVersion 36
26
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
27
+ }
28
+
29
+ buildFeatures {
30
+ buildConfig true
31
+ }
32
+
33
+ compileOptions {
34
+ sourceCompatibility JavaVersion.VERSION_17
35
+ targetCompatibility JavaVersion.VERSION_17
36
+ }
37
+
38
+ kotlinOptions {
39
+ jvmTarget = "17"
40
+ }
41
+
42
+ sourceSets {
43
+ main {
44
+ if (!isNewArchitectureEnabled()) {
45
+ // Old Architecture: use the hand-written spec that does NOT implement TurboModule
46
+ java.srcDirs += ["src/oldarch"]
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ repositories {
53
+ google()
54
+ mavenCentral()
55
+ }
56
+
57
+ dependencies {
58
+ implementation "com.facebook.react:react-android"
59
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:2.1.20"
60
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
61
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
62
+
63
+ // ExoPlayer (Media3)
64
+ implementation "androidx.media3:media3-exoplayer:1.3.1"
65
+ implementation "androidx.media3:media3-exoplayer-hls:1.3.1"
66
+ implementation "androidx.media3:media3-exoplayer-dash:1.3.1"
67
+ implementation "androidx.media3:media3-exoplayer-smoothstreaming:1.3.1"
68
+ implementation "androidx.media3:media3-session:1.3.1"
69
+ implementation "androidx.media3:media3-ui:1.3.1"
70
+ implementation "androidx.media3:media3-datasource-okhttp:1.3.1"
71
+
72
+ // OkHttp for custom headers
73
+ implementation "com.squareup.okhttp3:okhttp:4.12.0"
74
+
75
+ // AndroidX
76
+ implementation "androidx.core:core-ktx:1.12.0"
77
+ implementation "androidx.media:media:1.7.0"
78
+ }
79
+
80
+ def isNewArchitectureEnabled() {
81
+ return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
82
+ }
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+
4
+ <!-- Required permissions -->
5
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
6
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
7
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
8
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
9
+ <uses-permission android:name="android.permission.INTERNET" />
10
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
11
+
12
+ <application>
13
+ <!-- Background playback service -->
14
+ <service
15
+ android:name=".GliphPlayerService"
16
+ android:exported="true"
17
+ android:foregroundServiceType="mediaPlayback"
18
+ android:stopWithTask="false">
19
+ <intent-filter>
20
+ <action android:name="androidx.media3.session.MediaLibraryService" />
21
+ <action android:name="android.media.browse.MediaBrowserService" />
22
+ </intent-filter>
23
+ </service>
24
+
25
+ <!-- Android Auto support -->
26
+ <meta-data
27
+ android:name="com.google.android.gms.car.application"
28
+ android:resource="@xml/automotive_app_desc" />
29
+ </application>
30
+
31
+ </manifest>
@@ -0,0 +1,48 @@
1
+ package com.gliphplayer
2
+
3
+ import android.content.Context
4
+ import android.media.AudioDeviceInfo
5
+ import android.media.AudioManager
6
+ import android.os.Build
7
+ import com.facebook.react.bridge.Promise
8
+ import com.facebook.react.bridge.ReactApplicationContext
9
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
10
+ import com.facebook.react.bridge.ReactMethod
11
+
12
+ class DeviceInfoModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
13
+
14
+ override fun getName(): String {
15
+ return "DeviceInfoModule"
16
+ }
17
+
18
+ @ReactMethod
19
+ fun getActiveAudioDeviceName(promise: Promise) {
20
+ try {
21
+ val audioManager = reactApplicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
22
+
23
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
24
+ val devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
25
+
26
+ var bluetoothDeviceName: String? = null
27
+
28
+ for (device in devices) {
29
+ if (device.type == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP ||
30
+ device.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
31
+ bluetoothDeviceName = device.productName.toString()
32
+ break
33
+ }
34
+ }
35
+
36
+ if (bluetoothDeviceName != null) {
37
+ promise.resolve(bluetoothDeviceName)
38
+ } else {
39
+ promise.resolve(null)
40
+ }
41
+ } else {
42
+ promise.resolve(null)
43
+ }
44
+ } catch (e: Exception) {
45
+ promise.reject("ERROR", e.message)
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,16 @@
1
+ package com.gliphplayer
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ class DeviceInfoPackage : ReactPackage {
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
10
+ return listOf(DeviceInfoModule(reactContext))
11
+ }
12
+
13
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
14
+ return emptyList()
15
+ }
16
+ }