npm package: @maxcom/react-native-libmedia
Description: A Native Module for [React Native](http://facebook.github.io/react-native/), to use the [Libmedia](https://libeasy.alwaysdata.net/libmedia/) library.   Libmedia is a library of helpers dealing with media management, as a toolbox for developers to build 
Author: Maxcom
Latest version: 1.0.0

# react-native-libmedia

A Native Module for [React Native](http://facebook.github.io/react-native/),
to use the [Libmedia](https://libeasy.alwaysdata.net/libmedia/) library.  
Libmedia is a library of helpers dealing with media management, as a toolbox for developers to build their applications on Android.

WARNING: The module is for the Android platform only, as is the library.

## Requirements

This package, as a wrapper, is of no use without the library which is subject to a license for commercial usage.

## Installation

* Run the following commands from your React Native project directory:

	```bat
	npm install @maxcom/react-native-libmedia
	```

  * Additional step for React Native < 0.60:  
	```bat
	react-native link @maxcom/react-native-libmedia
	```

  * Additional step for React Native < 0.58:  
	If your gradle plugin version is already 3.0.0+, you should replace the deprecated `compile` dependency type
by the `implementation` dependency type in `android/app/build.gradle`.

  * Additional step for React Native < 0.56:  
	On build, Gradle 4.4 will produce a warning because of the presence of a '/' character in the project name derived
from a scoped node package name.
The support of such a character is annonced to have been deprecated and is scheduled to be removed in Gradle 5.0.  
An adjustment in the react-native tooling to replace '/' by '_' is effective as of version 0.56.
Before it, you have to do yourself the replacement of
`':@maxcom/react-native-libmedia'` by `':@maxcom_react-native-libmedia'` in these project files: `android/settings.gradle`
and `android/app/build.gradle`.

* Get the necessary jar files, as mentioned in [Integration Guidelines](https://libeasy.alwaysdata.net/libmedia/#integration)
Step 1 and Step 1a, but put them in `<your_project>\node_modules\@maxcom\react-native-libmedia\android\libs\`.

* Apply Integration Guidelines Step 2, Step 3. Step 4 is already embedded in the module.

## Usage

```javascript
import Libmedia from '@maxcom/react-native-libmedia';
```

## Module API

`Libmedia.createLocalSingleHttpServer()`

Creates the server, if not already done, as a LocalSingleHttpServer instance.

`Libmedia.createWifiSingleHttpServer()`

Creates the server, if not already done, as a WifiSingleHttpServer instance.

`Libmedia.setCipher(transformation: string, key: Array<number>, algorithm: string, iv?: Array<number>)`

Sets the Cipher for decryption.

Parameters:
* transformation - The name of the transformation, of the form: "algorithm/mode/padding" or "algorithm".
* key - The encryption key, as a byte array.
* algorithm - The name of the secret-key algorithm to associate with the key.
* iv - The Initialization Vector, as a byte array, if necessary for the transformation.

`Libmedia.setCipherFactory(transformation: string, key: Array<number>, algorithm: string, iv?: Array<number>)`

Sets the cipher factory for decryption.

Parameters: same as setCipher().

`Libmedia.clearCipher()`

Clears the cipher of the server.

`Libmedia.start()`

Starts the server.

`Libmedia.getUrl(path: string)`

Returns the URL to serve a resource specified by the provided path.

Parameters:
* path - The path of a resource.

`Libmedia.stop()`

Stops the server.

`Libmedia.destroy()`

Releases the reference to the server, after stopping it if necessary.

## Example

Hereunder is the source of a `TestLibmediaScreen.js`, as an example of a screen for a navigator with
[react-navigation](https://reactnavigation.org).

```jsx
/**
 * Copyright (c) 2019-present, Maxcom.
 */

import React, { Component } from 'react';
import { PermissionsAndroid } from "react-native";
import { WebView} from 'react-native-webview';

import Libmedia from '@maxcom/react-native-libmedia';

/**
 * Produce an array of numbers, one for each of the characters of a string.
 * WARNING: charCodeAt() returns the Unicode value of a character, in the range 0-65535.
 * As the aim is to return bytes, this simple converter is usable only with Ascii characters (code point < 0x80)
 */
const numberArrayFromAscii = (str) => str.split('').map(c => c.charCodeAt());

export default class TestLibmediaScreen extends Component<{}> {
  constructor(props) {
    super(props);
    __DEV__ && console.log(`${this.constructor.name} const`, props);
    this.state = {
      path: "",
    }
  }
  componentDidMount() {
    __DEV__ && console.log(`${this.constructor.name} componentDidMount`);
    this.requestStoragePermission();  // better to do it beforehand to avoid a fail on the first run
    this.setUp();
  }
  componentWillUnmount() {
    __DEV__ && console.log(`${this.constructor.name} componentWillUnmount`);
    this.tearDown();
  }

  async requestStoragePermission() {
    try {
      const isGranted = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE);
      if (!isGranted) {
        const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE);
        if (granted === PermissionsAndroid.RESULTS.GRANTED) {
          __DEV__ && console.log(`${this.constructor.name} Permission granted`);
        } else {
          __DEV__ && console.log(`${this.constructor.name} Permission denied`);
        }
      }
    } catch (err) {
      console.warn(err);
    }
  }

  async setUp() {
    try {
      await Libmedia.createLocalSingleHttpServer();
// uncomment one of these cases
      // no Cipher needed
      //var path = 'asset://clear.mp4';

      //var path = 'asset://encrypted.mp4';
      //await Libmedia.setCipher('ARC4', numberArrayFromAscii('BrianIsInTheKitchen'), 'ARC4', null);

      var path = '/mnt/sdcard/Movies/libm/secure.ctr.mp4';
      await Libmedia.setCipher('AES/CTR/NoPadding', numberArrayFromAscii('1234567890123456'), 'AES', new Array(16).fill(0));
//
      await Libmedia.start();

      path = await Libmedia.getUrl(path);
      __DEV__ && console.log(`${this.constructor.name} path ${path}`);
      this.setState({path});
    } catch(e) {
      console.error(this.constructor.name, e);
    }
  }

  async tearDown() {
    await Libmedia.stop();
    await Libmedia.destroy();
  }

  render() {
    const source = { html: `
<html><body>
<video src='${this.state.path}' controls></video>
</body></html>
    `};
    return (
<WebView style={{ flex: 1 }} source={source} />
    );
  }
}
```