react-native-tpstreams 0.1.8 → 0.1.10
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/README.md +356 -79
- package/android/src/main/java/com/tpstreams/FragmentModule.kt +3 -1
- package/android/src/main/java/com/tpstreams/PlayerFragment.kt +17 -1
- package/android/src/main/java/com/tpstreams/TpStreamsPlayerView.kt +15 -1
- package/android/src/main/java/com/tpstreams/TpStreamsPlayerViewManager.kt +9 -0
- package/android/src/main/java/com/tpstreams/TpstreamsModule.kt +7 -0
- package/android/src/main/java/com/tpstreams/TpstreamsPackage.kt +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,17 +8,31 @@ Video Component for TPStreams
|
|
|
8
8
|
npm install react-native-tpstreams
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
### Initializing TPStreams SDK
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
import React, { useState } from 'react';
|
|
15
|
-
import { View, Button, StyleSheet, NativeModules } from 'react-native';
|
|
16
|
-
import TpStreamsPlayerView from 'react-native-tpstreams';
|
|
13
|
+
First, import the package:
|
|
17
14
|
|
|
15
|
+
```javascript
|
|
16
|
+
import { NativeModules } from 'react-native';
|
|
18
17
|
const { Tpstreams } = NativeModules;
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Next, initialize the SDK with your organization ID:
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
Tpstreams.initializeTPSPlayer("YOUR_ORGANIZATION_ID");
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Make sure to replace `YOUR_ORGANIZATION_ID` with your actual organization ID. This should be called at the entry point of your application to ensure proper initialization.
|
|
27
|
+
|
|
28
|
+
## Play a Video
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
To play a video using the TPStreams Player SDK, use the `TpStreamsPlayerView` component:
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
import React, { useState } from 'react';
|
|
34
|
+
import { View, StyleSheet } from 'react-native';
|
|
35
|
+
import TpStreamsPlayerView from 'react-native-tpstreams';
|
|
22
36
|
|
|
23
37
|
const App = () => {
|
|
24
38
|
const [playerProps] = useState({
|
|
@@ -32,16 +46,6 @@ const App = () => {
|
|
|
32
46
|
return (
|
|
33
47
|
<View style={styles.container}>
|
|
34
48
|
<TpStreamsPlayerView {...playerProps} />
|
|
35
|
-
<View style={styles.buttonContainer}>
|
|
36
|
-
<Button title="Play" onPress={() => Tpstreams.play()} />
|
|
37
|
-
<Button title="Pause" onPress={() => Tpstreams.pause()} />
|
|
38
|
-
<Button title="Seek to 10s" onPress={() => Tpstreams.seekTo(10000)} />
|
|
39
|
-
<Button title="Get Current Time" onPress={() => Tpstreams.getCurrentTime().then(console.log)} />
|
|
40
|
-
<Button title="Get Duration" onPress={() => Tpstreams.getDuration().then(console.log)} />
|
|
41
|
-
<Button title="Get Playback Speed" onPress={() => Tpstreams.getPlaybackSpeed().then(console.log)} />
|
|
42
|
-
<Button title="Set Speed 1.5x" onPress={() => Tpstreams.setPlaybackSpeed(1.5)} />
|
|
43
|
-
<Button title="Set Speed 1x" onPress={() => Tpstreams.setPlaybackSpeed(1.0)} />
|
|
44
|
-
</View>
|
|
45
49
|
</View>
|
|
46
50
|
);
|
|
47
51
|
};
|
|
@@ -52,99 +56,372 @@ const styles = StyleSheet.create({
|
|
|
52
56
|
justifyContent: 'center',
|
|
53
57
|
alignItems: 'center',
|
|
54
58
|
},
|
|
55
|
-
buttonContainer: {
|
|
56
|
-
marginTop: 20,
|
|
57
|
-
width: '90%',
|
|
58
|
-
},
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
export default App;
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
Replace `ASSET_ID` and `ACCESS_TOKEN` with the actual assetId and accessToken of the video you wish to play.
|
|
64
65
|
|
|
65
66
|
## Player Props
|
|
66
|
-
|
|
67
67
|
The player component accepts the following props:
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
| Prop | Type | Required | Default | Description |
|
|
70
|
+
|----------------|---------|----------|---------------------------------|------------------------------------------------|
|
|
71
|
+
| `videoId` | string | Yes | - | The unique identifier of the video asset. |
|
|
72
|
+
| `accessToken` | string | Yes | - | The authentication token required to access the video. |
|
|
73
|
+
| `enableDownload` | boolean | No | `true` | Enables or disables video download. |
|
|
74
|
+
| `autoPlay` | boolean | No | `true` | Controls whether the video should start playing automatically. |
|
|
75
|
+
| `style` | object | No | `{ width: '100%', height: 300 }` | Defines the player’s width and height. |
|
|
76
|
+
|
|
77
|
+
# Player Methods
|
|
78
|
+
|
|
79
|
+
To use the `Tpstreams` module, first import `NativeModules` from `react-native` and get the `Tpstreams` instance:
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
import { NativeModules } from 'react-native';
|
|
83
|
+
const { Tpstreams } = NativeModules;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The `Tpstreams` module provides several methods to control video playback and manage player states. Below is a detailed explanation of each method:
|
|
87
|
+
|
|
88
|
+
## Play
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
Tpstreams.play();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Starts video playback. Call this method when you want the video to start playing or resume after being paused.
|
|
95
|
+
|
|
96
|
+
## Pause
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
Tpstreams.pause();
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Pauses video playback, allowing it to be resumed later from the same position.
|
|
103
|
+
|
|
104
|
+
## Seek To
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
Tpstreams.seekTo(position: number);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Seeks to a specific position in the video (in milliseconds).
|
|
111
|
+
|
|
112
|
+
**Example Usage:**
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
Tpstreams.seekTo(10000); // Jump to the 10-second mark
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Get Current Time
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
Tpstreams.getCurrentTime().then(console.log);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Gets the current playback position of the video (in milliseconds). Returns a promise that resolves with the current time.
|
|
125
|
+
|
|
126
|
+
## Get Duration
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
Tpstreams.getDuration().then(console.log);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Retrieves the total duration of the currently loaded video (in milliseconds). Returns a promise that resolves with the total duration.
|
|
133
|
+
|
|
134
|
+
## Get Buffered Time
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
Tpstreams.getBufferedTime().then(console.log);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Gets the amount of video data that has been buffered (in milliseconds). Returns a promise that resolves with the buffered time.
|
|
141
|
+
|
|
142
|
+
## Get Playback State
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
Tpstreams.getPlaybackState().then(console.log);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Gets the current playback state of the player (e.g., `playing`, `paused`, `buffering`). Returns a promise that resolves with the state.
|
|
149
|
+
|
|
150
|
+
## Get Play When Ready
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
Tpstreams.getPlayWhenReady().then(console.log);
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Checks if the player is set to start playback automatically. Returns a promise that resolves with a boolean value.
|
|
157
|
+
|
|
158
|
+
## Set Play When Ready
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
Tpstreams.setPlayWhenReady(true); // Enable autoplay
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Controls whether the player should start playback automatically when loaded.
|
|
165
|
+
|
|
166
|
+
## Get Playback Speed
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
Tpstreams.getPlaybackSpeed().then(console.log);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Gets the current playback speed of the video. Returns a promise that resolves with the speed value.
|
|
173
|
+
|
|
174
|
+
## Set Playback Speed
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
Tpstreams.setPlaybackSpeed(1.5); // Play at 1.5x speed
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Changes the playback speed of the video.
|
|
181
|
+
|
|
182
|
+
## Release
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
Tpstreams.release();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Releases the player resources, stopping playback and hiding the player UI. Once called, the player cannot be used again unless reinitialized.
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# Player Events
|
|
192
|
+
|
|
193
|
+
`Tpstreams` provides event listeners to handle various player events. Below are the available events and how to use them:
|
|
194
|
+
|
|
195
|
+
## Listening to Events
|
|
71
196
|
|
|
72
|
-
|
|
73
|
-
The authentication token required to access the video.
|
|
197
|
+
To subscribe to player events, use the `NativeEventEmitter` from `react-native` with `TpstreamsModule`:
|
|
74
198
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
199
|
+
```js
|
|
200
|
+
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
201
|
+
|
|
202
|
+
const { Tpstreams } = NativeModules;
|
|
203
|
+
const eventEmitter = new NativeEventEmitter(Tpstreams);
|
|
204
|
+
|
|
205
|
+
const subscription = eventEmitter.addListener('onPlaybackStateChanged', (state) => {
|
|
206
|
+
console.log('Playback State Changed:', state);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Remember to remove the listener when unmounting
|
|
210
|
+
subscription.remove();
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Available Events
|
|
79
214
|
|
|
80
|
-
###
|
|
81
|
-
|
|
82
|
-
- `true` → Video starts playing automatically (default).
|
|
83
|
-
- `false` → User must manually start playback.
|
|
215
|
+
### onPlaybackStateChanged
|
|
216
|
+
Triggered when the playback state changes.
|
|
84
217
|
|
|
85
|
-
### `style` (object, optional)
|
|
86
|
-
Defines the player’s width and height.
|
|
87
|
-
Example:
|
|
88
218
|
```js
|
|
89
|
-
|
|
219
|
+
eventEmitter.addListener('onPlaybackStateChanged', (state) => {
|
|
220
|
+
console.log('Playback State:', state);
|
|
221
|
+
});
|
|
90
222
|
```
|
|
91
|
-
## Player Methods
|
|
92
223
|
|
|
93
|
-
###
|
|
94
|
-
|
|
224
|
+
### onAccessTokenExpired
|
|
225
|
+
Triggered when the access token expires (requires refresh).
|
|
95
226
|
|
|
96
|
-
|
|
97
|
-
|
|
227
|
+
```js
|
|
228
|
+
eventEmitter.addListener('onAccessTokenExpired', () => {
|
|
229
|
+
console.log('Access token expired, please refresh.');
|
|
230
|
+
});
|
|
231
|
+
```
|
|
98
232
|
|
|
99
|
-
###
|
|
100
|
-
|
|
101
|
-
For example, `seekTo(10000)` moves the playback to 10 seconds.
|
|
233
|
+
### onMarkerCallback
|
|
234
|
+
Triggered when a marker (timestamp) is reached during playback.
|
|
102
235
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
236
|
+
```js
|
|
237
|
+
eventEmitter.addListener('onMarkerCallback', (marker) => {
|
|
238
|
+
console.log('Marker reached:', marker);
|
|
239
|
+
});
|
|
240
|
+
```
|
|
106
241
|
|
|
107
|
-
###
|
|
108
|
-
|
|
109
|
-
Returns a promise that resolves with the length of the video.
|
|
242
|
+
### onDeviceInfoChanged
|
|
243
|
+
Triggered when the device information changes.
|
|
110
244
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
245
|
+
```js
|
|
246
|
+
eventEmitter.addListener('onDeviceInfoChanged', (info) => {
|
|
247
|
+
console.log('Device info changed:', info);
|
|
248
|
+
});
|
|
249
|
+
```
|
|
114
250
|
|
|
115
|
-
###
|
|
116
|
-
|
|
117
|
-
Returns a promise that resolves with a state value.
|
|
251
|
+
### onFullScreenChanged
|
|
252
|
+
Triggered when the fullscreen mode changes.
|
|
118
253
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
254
|
+
```js
|
|
255
|
+
eventEmitter.addListener('onFullScreenChanged', (isFullscreen) => {
|
|
256
|
+
console.log('Fullscreen mode:', isFullscreen);
|
|
257
|
+
});
|
|
258
|
+
```
|
|
122
259
|
|
|
123
|
-
###
|
|
124
|
-
|
|
125
|
-
Pass `true` to enable autoplay or `false` to disable it.
|
|
260
|
+
### onIsLoadingChanged
|
|
261
|
+
Triggered when the player’s loading state changes.
|
|
126
262
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
263
|
+
```js
|
|
264
|
+
eventEmitter.addListener('onIsLoadingChanged', (isLoading) => {
|
|
265
|
+
console.log('Loading state changed:', isLoading);
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### onIsPlayingChanged
|
|
270
|
+
Triggered when the player’s playing state changes.
|
|
271
|
+
|
|
272
|
+
```js
|
|
273
|
+
eventEmitter.addListener('onIsPlayingChanged', (isPlaying) => {
|
|
274
|
+
console.log('Playing state:', isPlaying);
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### onPlayerError
|
|
279
|
+
Triggered when the player encounters an error.
|
|
280
|
+
|
|
281
|
+
```js
|
|
282
|
+
eventEmitter.addListener('onPlayerError', (error) => {
|
|
283
|
+
console.log('Player Error:', error);
|
|
284
|
+
});
|
|
285
|
+
```
|
|
130
286
|
|
|
131
|
-
###
|
|
132
|
-
|
|
133
|
-
For example, `setPlaybackSpeed(2.0)` doubles the speed, while `setPlaybackSpeed(0.5)` slows it down.
|
|
287
|
+
### onSeekBackIncrementChanged
|
|
288
|
+
Triggered when the seek-back increment value changes.
|
|
134
289
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
290
|
+
```js
|
|
291
|
+
eventEmitter.addListener('onSeekBackIncrementChanged', (value) => {
|
|
292
|
+
console.log('Seek back increment changed:', value);
|
|
293
|
+
});
|
|
294
|
+
```
|
|
138
295
|
|
|
296
|
+
### onSeekForwardIncrementChanged
|
|
297
|
+
Triggered when the seek-forward increment value changes.
|
|
139
298
|
|
|
140
|
-
|
|
299
|
+
```js
|
|
300
|
+
eventEmitter.addListener('onSeekForwardIncrementChanged', (value) => {
|
|
301
|
+
console.log('Seek forward increment changed:', value);
|
|
302
|
+
});
|
|
303
|
+
```
|
|
141
304
|
|
|
142
|
-
|
|
305
|
+
### onTimelineChanged
|
|
306
|
+
Triggered when the timeline of the player changes.
|
|
143
307
|
|
|
144
|
-
|
|
308
|
+
```js
|
|
309
|
+
eventEmitter.addListener('onTimelineChanged', (timeline) => {
|
|
310
|
+
console.log('Timeline changed:', timeline);
|
|
311
|
+
});
|
|
312
|
+
```
|
|
145
313
|
|
|
146
|
-
|
|
314
|
+
### onTracksChanged
|
|
315
|
+
Triggered when the available tracks change (e.g., audio/video/subtitles).
|
|
147
316
|
|
|
148
|
-
|
|
317
|
+
```js
|
|
318
|
+
eventEmitter.addListener('onTracksChanged', (tracks) => {
|
|
319
|
+
console.log('Tracks changed:', tracks);
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
# Download Module
|
|
324
|
+
|
|
325
|
+
The `Download Module` in `Tpstreams` allows users to manage offline video downloads efficiently. This includes observing download progress, pausing, resuming, canceling, and deleting downloads.
|
|
326
|
+
|
|
327
|
+
## Observing Download Data
|
|
328
|
+
|
|
329
|
+
To start observing the download data, call the `observeDownloadData` method from `FragmentModule`.
|
|
330
|
+
|
|
331
|
+
```js
|
|
332
|
+
import { NativeModules, DeviceEventEmitter } from 'react-native';
|
|
333
|
+
|
|
334
|
+
const { FragmentModule } = NativeModules;
|
|
335
|
+
FragmentModule.observeDownloadData();
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Once initialized, the module will emit events whenever the download data changes.
|
|
339
|
+
|
|
340
|
+
## Listening to Download Events
|
|
341
|
+
|
|
342
|
+
To listen for download state changes, use `DeviceEventEmitter`:
|
|
343
|
+
|
|
344
|
+
```js
|
|
345
|
+
const subscription = DeviceEventEmitter.addListener(
|
|
346
|
+
'onDownloadDataChanged',
|
|
347
|
+
(event) => {
|
|
348
|
+
console.log('Download data updated:', event.assets);
|
|
349
|
+
}
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
// Remember to remove the listener when unmounting
|
|
353
|
+
subscription.remove();
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Managing Downloads
|
|
357
|
+
|
|
358
|
+
### Pause Download
|
|
359
|
+
Pauses an active download.
|
|
360
|
+
|
|
361
|
+
```js
|
|
362
|
+
FragmentModule.pauseDownload(videoId);
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Resume Download
|
|
366
|
+
Resumes a paused download.
|
|
367
|
+
|
|
368
|
+
```js
|
|
369
|
+
FragmentModule.resumeDownload(videoId);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Cancel Download
|
|
373
|
+
Cancels an ongoing download.
|
|
374
|
+
|
|
375
|
+
```js
|
|
376
|
+
FragmentModule.cancelDownload(videoId);
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Delete Download
|
|
380
|
+
Deletes a completed download from storage.
|
|
381
|
+
|
|
382
|
+
```js
|
|
383
|
+
FragmentModule.deleteDownload(videoId);
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Rendering a Download List
|
|
387
|
+
|
|
388
|
+
Below is a sample implementation of a download list UI using `FlatList` in React Native:
|
|
389
|
+
|
|
390
|
+
```js
|
|
391
|
+
import React, { useState, useEffect } from 'react';
|
|
392
|
+
import { SafeAreaView, Text, FlatList, View, Button, DeviceEventEmitter } from 'react-native';
|
|
393
|
+
import { NativeModules } from 'react-native';
|
|
394
|
+
|
|
395
|
+
const { FragmentModule } = NativeModules;
|
|
396
|
+
|
|
397
|
+
const DownloadListScreen = () => {
|
|
398
|
+
const [downloads, setDownloads] = useState([]);
|
|
399
|
+
|
|
400
|
+
useEffect(() => {
|
|
401
|
+
FragmentModule.observeDownloadData();
|
|
402
|
+
const subscription = DeviceEventEmitter.addListener('onDownloadDataChanged', (event) => {
|
|
403
|
+
setDownloads(event.assets);
|
|
404
|
+
});
|
|
405
|
+
return () => subscription.remove();
|
|
406
|
+
}, []);
|
|
407
|
+
|
|
408
|
+
const renderItem = ({ item }) => (
|
|
409
|
+
<View>
|
|
410
|
+
<Text>{item.title} - {item.percentage}%</Text>
|
|
411
|
+
{item.status === 'DOWNLOADING' && <Button title="Pause" onPress={() => FragmentModule.pauseDownload(item.videoId)} />}
|
|
412
|
+
{item.status === 'COMPLETE' && <Button title="Delete" onPress={() => FragmentModule.deleteDownload(item.videoId)} />}
|
|
413
|
+
{item.status === 'PAUSED' && <Button title="Resume" onPress={() => FragmentModule.resumeDownload(item.videoId)} />}
|
|
414
|
+
</View>
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
return (
|
|
418
|
+
<SafeAreaView>
|
|
419
|
+
<FlatList data={downloads} keyExtractor={(item) => item.videoId} renderItem={renderItem} />
|
|
420
|
+
</SafeAreaView>
|
|
421
|
+
);
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
export default DownloadListScreen;
|
|
425
|
+
```
|
|
149
426
|
|
|
150
|
-
|
|
427
|
+
This component observes download events and dynamically updates the list with buttons for user interactions.
|
|
@@ -35,7 +35,7 @@ class FragmentModule(reactContext: ReactApplicationContext) : ReactContextBaseJa
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
@ReactMethod
|
|
38
|
-
fun showCustomFragment(videoId: String, accessToken: String, enableDownload: Boolean, autoPlay: Boolean) {
|
|
38
|
+
fun showCustomFragment(videoId: String, accessToken: String, enableDownload: Boolean, autoPlay: Boolean, startAt: Int, offlineLicenseExpireTime: Int) {
|
|
39
39
|
Log.e("FragmentModule", "showCustomFragment() called")
|
|
40
40
|
// Ensure the currentActivity is a FragmentActivity
|
|
41
41
|
val activity = currentActivity as? FragmentActivity
|
|
@@ -49,6 +49,8 @@ class FragmentModule(reactContext: ReactApplicationContext) : ReactContextBaseJa
|
|
|
49
49
|
bundle.putString("ACCESS_TOKEN", accessToken)
|
|
50
50
|
bundle.putBoolean("ENABLE_DOWNLOAD_SUPPORT", enableDownload)
|
|
51
51
|
bundle.putBoolean("AUTO_PLAY", autoPlay)
|
|
52
|
+
bundle.putInt("START_AT", startAt)
|
|
53
|
+
bundle.putInt("OFFLINE_LICENSE_EXPIRE_TIME", offlineLicenseExpireTime)
|
|
52
54
|
val fragment = PlayerFragment()
|
|
53
55
|
fragment.setArguments(bundle)
|
|
54
56
|
|
|
@@ -19,6 +19,8 @@ import com.tpstream.player.Timeline
|
|
|
19
19
|
import com.tpstream.player.DeviceInfo
|
|
20
20
|
import com.tpstreams.TpstreamsModule
|
|
21
21
|
|
|
22
|
+
internal typealias onAccessTokenCallbase = (String) -> Unit
|
|
23
|
+
|
|
22
24
|
class PlayerFragment : Fragment() {
|
|
23
25
|
|
|
24
26
|
lateinit var player: TpStreamPlayer
|
|
@@ -28,6 +30,10 @@ class PlayerFragment : Fragment() {
|
|
|
28
30
|
private var accessToken :String = ""
|
|
29
31
|
private var enableDownloadSupport :Boolean = true
|
|
30
32
|
private var setAutoPlay :Boolean = true
|
|
33
|
+
private var startAt :Int = 0
|
|
34
|
+
private var offlineLicenseExpireTime :Int = 15
|
|
35
|
+
|
|
36
|
+
private var accessTokenCallback : onAccessTokenCallbase? = null
|
|
31
37
|
|
|
32
38
|
companion object {
|
|
33
39
|
var instance: PlayerFragment? = null
|
|
@@ -41,6 +47,8 @@ class PlayerFragment : Fragment() {
|
|
|
41
47
|
accessToken = bundle.getString("ACCESS_TOKEN") ?: ""
|
|
42
48
|
enableDownloadSupport = bundle.getBoolean("ENABLE_DOWNLOAD_SUPPORT", true)
|
|
43
49
|
setAutoPlay = bundle.getBoolean("AUTO_PLAY", true)
|
|
50
|
+
startAt = bundle.getInt("START_AT", 0)
|
|
51
|
+
offlineLicenseExpireTime = bundle.getInt("OFFLINE_LICENSE_EXPIRE_TIME", 15)
|
|
44
52
|
|
|
45
53
|
}
|
|
46
54
|
}
|
|
@@ -73,6 +81,8 @@ class PlayerFragment : Fragment() {
|
|
|
73
81
|
.setAccessToken(accessToken)
|
|
74
82
|
.enableDownloadSupport(enableDownloadSupport)
|
|
75
83
|
.setAutoPlay(setAutoPlay)
|
|
84
|
+
.startAt(startAt.toLong())
|
|
85
|
+
.setOfflineLicenseExpireTime(offlineLicenseExpireTime)
|
|
76
86
|
.build()
|
|
77
87
|
requireActivity().runOnUiThread {
|
|
78
88
|
player.load(parameters)
|
|
@@ -90,8 +100,9 @@ class PlayerFragment : Fragment() {
|
|
|
90
100
|
}
|
|
91
101
|
|
|
92
102
|
override fun onAccessTokenExpired(videoId: String, callback: (String) -> Unit) {
|
|
103
|
+
Log.d("ReactNativeJS", "onTokenExpired: $videoId")
|
|
104
|
+
accessTokenCallback = callback
|
|
93
105
|
sendEvent("onAccessTokenExpired", videoId)
|
|
94
|
-
callback(accessToken)
|
|
95
106
|
}
|
|
96
107
|
|
|
97
108
|
override fun onMarkerCallback(timesInSeconds: Long) {
|
|
@@ -196,6 +207,11 @@ class PlayerFragment : Fragment() {
|
|
|
196
207
|
}
|
|
197
208
|
}
|
|
198
209
|
|
|
210
|
+
fun setNewAccessToken(token: String) {
|
|
211
|
+
accessTokenCallback?.invoke(token)
|
|
212
|
+
accessTokenCallback = null
|
|
213
|
+
}
|
|
214
|
+
|
|
199
215
|
override fun onResume() {
|
|
200
216
|
super.onResume()
|
|
201
217
|
Log.d("ReactNativeJS", "onResume: ")
|
|
@@ -17,6 +17,8 @@ class TpStreamsPlayerView @JvmOverloads constructor(
|
|
|
17
17
|
private var accessToken: String? = null
|
|
18
18
|
private var enableDownload: Boolean = true
|
|
19
19
|
private var autoPlay :Boolean = true
|
|
20
|
+
private var startAt :Int = 0
|
|
21
|
+
private var offlineLicenseExpireTime :Int = 15
|
|
20
22
|
private var fragmentModule: FragmentModule? = null
|
|
21
23
|
|
|
22
24
|
private val job = SupervisorJob()
|
|
@@ -54,6 +56,16 @@ class TpStreamsPlayerView @JvmOverloads constructor(
|
|
|
54
56
|
updateFragment()
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
fun setStartTime(startAt: Int?) {
|
|
60
|
+
this.startAt = startAt ?: 0
|
|
61
|
+
updateFragment()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fun setOfflineLicenseExpireTime(offlineLicenseExpireTime: Int?) {
|
|
65
|
+
this.offlineLicenseExpireTime = offlineLicenseExpireTime ?: 15
|
|
66
|
+
updateFragment()
|
|
67
|
+
}
|
|
68
|
+
|
|
57
69
|
private fun updateFragment() {
|
|
58
70
|
if (!videoId.isNullOrEmpty() && !accessToken.isNullOrEmpty()) {
|
|
59
71
|
updateJob?.cancel()
|
|
@@ -64,7 +76,9 @@ class TpStreamsPlayerView @JvmOverloads constructor(
|
|
|
64
76
|
videoId!!,
|
|
65
77
|
accessToken!!,
|
|
66
78
|
enableDownload,
|
|
67
|
-
autoPlay ?: true
|
|
79
|
+
autoPlay ?: true,
|
|
80
|
+
startAt,
|
|
81
|
+
offlineLicenseExpireTime,
|
|
68
82
|
)
|
|
69
83
|
}
|
|
70
84
|
}
|
|
@@ -32,6 +32,15 @@ class TpStreamsPlayerViewManager : SimpleViewManager<TpStreamsPlayerView>() {
|
|
|
32
32
|
view.setAutoPlay(autoPlay)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
@ReactProp(name = "startAt")
|
|
36
|
+
fun setStartTime(view: TpStreamsPlayerView, startAt: Int?) {
|
|
37
|
+
view.setStartTime(startAt ?: 0)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@ReactProp(name = "offlineLicenseExpireTime")
|
|
41
|
+
fun setOfflineLicenseExpireTime(view: TpStreamsPlayerView, offlineLicenseExpireTime: Int?) {
|
|
42
|
+
view.setOfflineLicenseExpireTime(offlineLicenseExpireTime ?: 15)
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
|
|
@@ -142,6 +142,13 @@ class TpstreamsModule(reactContext: ReactApplicationContext) :
|
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
@ReactMethod
|
|
146
|
+
fun setNewAccessToken(token: String) {
|
|
147
|
+
runOnMainThread {
|
|
148
|
+
getPlayerFragment()?.setNewAccessToken(token)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
145
152
|
private fun getPlayerFragment(): PlayerFragment? {
|
|
146
153
|
return PlayerFragment.instance?.takeIf { it.player != null }
|
|
147
154
|
}
|
|
@@ -7,7 +7,7 @@ import com.facebook.react.uimanager.ViewManager
|
|
|
7
7
|
|
|
8
8
|
class TpstreamsPackage : ReactPackage {
|
|
9
9
|
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
-
return listOf(TpstreamsModule(reactContext))
|
|
10
|
+
return listOf(TpstreamsModule(reactContext), FragmentModule(reactContext))
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|