@capgo/native-audio 7.10.3 → 7.11.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.
- package/README.md +34 -1
- package/android/build.gradle +22 -1
- package/android/src/main/java/ee/forgr/audio/HlsAvailabilityChecker.java +84 -0
- package/android/src/main/java/ee/forgr/audio/NativeAudio.java +47 -2
- package/ios/Sources/NativeAudioPlugin/Plugin.swift +1 -1
- package/package.json +6 -3
- package/scripts/configure-dependencies.js +251 -0
package/README.md
CHANGED
|
@@ -103,7 +103,40 @@ You can also consume the iOS implementation via Swift Package Manager. In Xcode
|
|
|
103
103
|
|
|
104
104
|
## Configuration
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
### Optional HLS/m3u8 Streaming (Android)
|
|
107
|
+
|
|
108
|
+
By default, HLS streaming support is **enabled** for backward compatibility. However, it adds approximately **4MB** to your Android APK size due to the `media3-exoplayer-hls` dependency.
|
|
109
|
+
|
|
110
|
+
If you don't need HLS/m3u8 streaming support, you can disable it to reduce your APK size:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// capacitor.config.ts
|
|
114
|
+
import type { CapacitorConfig } from '@capacitor/cli';
|
|
115
|
+
|
|
116
|
+
const config: CapacitorConfig = {
|
|
117
|
+
appId: 'com.example.app',
|
|
118
|
+
appName: 'My App',
|
|
119
|
+
plugins: {
|
|
120
|
+
NativeAudio: {
|
|
121
|
+
hls: false // Disable HLS to reduce APK size by ~4MB
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export default config;
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
After changing the configuration, run:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npx cap sync
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Notes:**
|
|
136
|
+
- iOS uses native AVPlayer for HLS, so this setting only affects Android
|
|
137
|
+
- If HLS is disabled and you try to play an `.m3u8` file, you'll get a clear error message explaining how to enable it
|
|
138
|
+
- The default is `hls: true` to maintain backward compatibility
|
|
139
|
+
|
|
107
140
|
<docgen-config>
|
|
108
141
|
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
109
142
|
|
package/android/build.gradle
CHANGED
|
@@ -3,6 +3,10 @@ ext {
|
|
|
3
3
|
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
|
|
4
4
|
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
|
|
5
5
|
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
|
6
|
+
|
|
7
|
+
// Read HLS configuration from gradle.properties (set by hook script)
|
|
8
|
+
// Default to 'true' for backward compatibility
|
|
9
|
+
includeHls = project.findProperty('nativeAudio.hls.include') ?: 'true'
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
buildscript {
|
|
@@ -40,6 +44,16 @@ android {
|
|
|
40
44
|
sourceCompatibility JavaVersion.VERSION_21
|
|
41
45
|
targetCompatibility JavaVersion.VERSION_21
|
|
42
46
|
}
|
|
47
|
+
|
|
48
|
+
// Exclude StreamAudioAsset when HLS is disabled
|
|
49
|
+
// StreamAudioAsset depends on HlsMediaSource which is only available with media3-exoplayer-hls
|
|
50
|
+
sourceSets {
|
|
51
|
+
main {
|
|
52
|
+
if (includeHls != 'true') {
|
|
53
|
+
java.exclude '**/StreamAudioAsset.java'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
43
57
|
}
|
|
44
58
|
|
|
45
59
|
repositories {
|
|
@@ -56,7 +70,14 @@ dependencies {
|
|
|
56
70
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
57
71
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
58
72
|
implementation 'androidx.media3:media3-exoplayer:1.8.0'
|
|
59
|
-
|
|
73
|
+
|
|
74
|
+
// HLS (m3u8) streaming support - optional dependency
|
|
75
|
+
// When disabled, reduces APK size by ~4MB
|
|
76
|
+
// Configure via capacitor.config.ts: plugins.NativeAudio.hls = false
|
|
77
|
+
if (includeHls == 'true') {
|
|
78
|
+
implementation 'androidx.media3:media3-exoplayer-hls:1.8.0'
|
|
79
|
+
}
|
|
80
|
+
|
|
60
81
|
implementation 'androidx.media3:media3-session:1.8.0'
|
|
61
82
|
implementation 'androidx.media3:media3-transformer:1.5.1'
|
|
62
83
|
implementation 'androidx.media3:media3-ui:1.5.1'
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
package ee.forgr.audio;
|
|
2
|
+
|
|
3
|
+
import android.util.Log;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Utility class to check if HLS (m3u8) streaming dependencies are available at runtime.
|
|
7
|
+
*
|
|
8
|
+
* This allows the plugin to gracefully handle cases where the HLS dependency
|
|
9
|
+
* (media3-exoplayer-hls) is excluded to reduce APK size.
|
|
10
|
+
*
|
|
11
|
+
* Users who don't need HLS streaming support can disable it in capacitor.config.ts:
|
|
12
|
+
*
|
|
13
|
+
* plugins: {
|
|
14
|
+
* NativeAudio: {
|
|
15
|
+
* hls: false // Reduces APK size by ~4MB
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
public class HlsAvailabilityChecker {
|
|
20
|
+
|
|
21
|
+
private static final String TAG = "HlsAvailabilityChecker";
|
|
22
|
+
private static Boolean hlsAvailable = null;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Check if a class is available at runtime using reflection.
|
|
26
|
+
*/
|
|
27
|
+
private static boolean isClassAvailable(String className) {
|
|
28
|
+
try {
|
|
29
|
+
Class.forName(className);
|
|
30
|
+
return true;
|
|
31
|
+
} catch (ClassNotFoundException e) {
|
|
32
|
+
return false;
|
|
33
|
+
} catch (Exception e) {
|
|
34
|
+
Log.e(TAG, "Unexpected error checking class availability: " + className, e);
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if HLS streaming dependencies are available.
|
|
41
|
+
* Results are cached for performance.
|
|
42
|
+
*
|
|
43
|
+
* @return true if HLS classes are available, false otherwise
|
|
44
|
+
*/
|
|
45
|
+
public static boolean isHlsAvailable() {
|
|
46
|
+
if (hlsAvailable != null) {
|
|
47
|
+
return hlsAvailable;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Check for the critical HLS classes from media3-exoplayer-hls
|
|
51
|
+
String[] hlsClasses = { "androidx.media3.exoplayer.hls.HlsMediaSource", "androidx.media3.exoplayer.hls.HlsMediaSource$Factory" };
|
|
52
|
+
|
|
53
|
+
boolean allAvailable = true;
|
|
54
|
+
for (String className : hlsClasses) {
|
|
55
|
+
if (!isClassAvailable(className)) {
|
|
56
|
+
allAvailable = false;
|
|
57
|
+
Log.w(TAG, "HLS dependency class not available: " + className);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
hlsAvailable = allAvailable;
|
|
62
|
+
|
|
63
|
+
if (!allAvailable) {
|
|
64
|
+
Log.i(
|
|
65
|
+
TAG,
|
|
66
|
+
"HLS streaming support is not available. " +
|
|
67
|
+
"To enable m3u8 streaming, set 'hls: true' in capacitor.config.ts under NativeAudio plugin config " +
|
|
68
|
+
"and run 'npx cap sync'."
|
|
69
|
+
);
|
|
70
|
+
} else {
|
|
71
|
+
Log.d(TAG, "HLS streaming support is available.");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return allAvailable;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Reset the cached availability check.
|
|
79
|
+
* Useful for testing purposes.
|
|
80
|
+
*/
|
|
81
|
+
public static void resetCache() {
|
|
82
|
+
hlsAvailable = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -665,8 +665,22 @@ public class NativeAudio extends Plugin implements AudioManager.OnAudioFocusChan
|
|
|
665
665
|
}
|
|
666
666
|
|
|
667
667
|
if (assetPath.endsWith(".m3u8")) {
|
|
668
|
-
// HLS Stream -
|
|
669
|
-
|
|
668
|
+
// HLS Stream - check if HLS support is available
|
|
669
|
+
if (!HlsAvailabilityChecker.isHlsAvailable()) {
|
|
670
|
+
call.reject(
|
|
671
|
+
"HLS streaming (.m3u8) is not available. " +
|
|
672
|
+
"The media3-exoplayer-hls dependency is not included. " +
|
|
673
|
+
"To enable HLS support, set 'hls: true' in capacitor.config.ts under NativeAudio plugin config " +
|
|
674
|
+
"and run 'npx cap sync'. This will increase APK size by ~4MB."
|
|
675
|
+
);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
// HLS Stream - create via reflection to allow compile-time exclusion
|
|
679
|
+
AudioAsset streamAudioAsset = createStreamAudioAsset(audioId, uri, volume, requestHeaders);
|
|
680
|
+
if (streamAudioAsset == null) {
|
|
681
|
+
call.reject("Failed to create HLS stream player. HLS support may not be properly configured.");
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
670
684
|
audioAssetList.put(audioId, streamAudioAsset);
|
|
671
685
|
call.resolve(status);
|
|
672
686
|
} else {
|
|
@@ -784,6 +798,37 @@ public class NativeAudio extends Plugin implements AudioManager.OnAudioFocusChan
|
|
|
784
798
|
return (value != null && !value.isEmpty() && !value.equals("null"));
|
|
785
799
|
}
|
|
786
800
|
|
|
801
|
+
/**
|
|
802
|
+
* Creates a StreamAudioAsset via reflection.
|
|
803
|
+
* This allows the StreamAudioAsset class to be excluded at compile time when HLS is disabled,
|
|
804
|
+
* reducing APK size by ~4MB.
|
|
805
|
+
*
|
|
806
|
+
* @param audioId The unique identifier for the audio asset
|
|
807
|
+
* @param uri The URI of the HLS stream
|
|
808
|
+
* @param volume The initial volume (0.0 to 1.0)
|
|
809
|
+
* @param headers Optional HTTP headers for the request
|
|
810
|
+
* @return The created AudioAsset, or null if creation failed
|
|
811
|
+
*/
|
|
812
|
+
private AudioAsset createStreamAudioAsset(String audioId, Uri uri, float volume, java.util.Map<String, String> headers) {
|
|
813
|
+
try {
|
|
814
|
+
Class<?> streamAudioAssetClass = Class.forName("ee.forgr.audio.StreamAudioAsset");
|
|
815
|
+
java.lang.reflect.Constructor<?> constructor = streamAudioAssetClass.getConstructor(
|
|
816
|
+
NativeAudio.class,
|
|
817
|
+
String.class,
|
|
818
|
+
Uri.class,
|
|
819
|
+
float.class,
|
|
820
|
+
java.util.Map.class
|
|
821
|
+
);
|
|
822
|
+
return (AudioAsset) constructor.newInstance(this, audioId, uri, volume, headers);
|
|
823
|
+
} catch (ClassNotFoundException e) {
|
|
824
|
+
Log.e(TAG, "StreamAudioAsset class not found. HLS support is not included in this build.", e);
|
|
825
|
+
return null;
|
|
826
|
+
} catch (Exception e) {
|
|
827
|
+
Log.e(TAG, "Failed to create StreamAudioAsset", e);
|
|
828
|
+
return null;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
787
832
|
private void stopAudio(String audioId) throws Exception {
|
|
788
833
|
if (!audioAssetList.containsKey(audioId)) {
|
|
789
834
|
throw new Exception(ERROR_ASSET_NOT_LOADED);
|
|
@@ -13,7 +13,7 @@ enum MyError: Error {
|
|
|
13
13
|
// swiftlint:disable type_body_length file_length
|
|
14
14
|
@objc(NativeAudio)
|
|
15
15
|
public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
|
16
|
-
private let pluginVersion: String = "7.
|
|
16
|
+
private let pluginVersion: String = "7.11.0"
|
|
17
17
|
public let identifier = "NativeAudio"
|
|
18
18
|
public let jsName = "NativeAudio"
|
|
19
19
|
public let pluginMethods: [CAPPluginMethod] = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/native-audio",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.11.0",
|
|
4
4
|
"description": "A native plugin for native audio engine",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"main": "dist/plugin.cjs.js",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"ios/Sources",
|
|
15
15
|
"ios/Tests",
|
|
16
16
|
"Package.swift",
|
|
17
|
-
"CapgoNativeAudio.podspec"
|
|
17
|
+
"CapgoNativeAudio.podspec",
|
|
18
|
+
"scripts/configure-dependencies.js"
|
|
18
19
|
],
|
|
19
20
|
"author": "Martin Donadieu",
|
|
20
21
|
"repository": {
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
"native"
|
|
34
35
|
],
|
|
35
36
|
"scripts": {
|
|
37
|
+
"capacitor:sync:after": "node scripts/configure-dependencies.js",
|
|
36
38
|
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
|
37
39
|
"verify:ios": "xcodebuild -scheme CapgoNativeAudio -destination generic/platform=iOS",
|
|
38
40
|
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
@@ -45,7 +47,8 @@
|
|
|
45
47
|
"prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
46
48
|
"swiftlint": "node-swiftlint",
|
|
47
49
|
"docgen": "docgen --api NativeAudio --output-readme README.md --output-json dist/docs.json",
|
|
48
|
-
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
50
|
+
"build": "npm run clean && npm run docgen && npm run build:scripts && tsc && rollup -c rollup.config.mjs",
|
|
51
|
+
"build:scripts": "tsc -p scripts/tsconfig.json",
|
|
49
52
|
"clean": "rimraf ./dist",
|
|
50
53
|
"watch": "tsc --watch",
|
|
51
54
|
"prepublishOnly": "npm run build"
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Capacitor Hook Script: Configure Optional HLS Dependency
|
|
5
|
+
*
|
|
6
|
+
* This script runs during `npx cap sync` and configures whether to include
|
|
7
|
+
* the HLS (m3u8) streaming dependency based on capacitor.config.ts settings.
|
|
8
|
+
*
|
|
9
|
+
* By default, HLS is enabled for backward compatibility.
|
|
10
|
+
* To disable HLS and reduce APK size by ~4MB, set:
|
|
11
|
+
*
|
|
12
|
+
* plugins: {
|
|
13
|
+
* NativeAudio: {
|
|
14
|
+
* hls: false
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* Environment variables provided by Capacitor:
|
|
19
|
+
* - CAPACITOR_ROOT_DIR: Root directory of the consuming app
|
|
20
|
+
* - CAPACITOR_CONFIG: JSON stringified config object
|
|
21
|
+
* - CAPACITOR_PLATFORM_NAME: Platform name (android, ios, web)
|
|
22
|
+
* - process.cwd(): Plugin root directory
|
|
23
|
+
*/
|
|
24
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
27
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
28
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
29
|
+
}
|
|
30
|
+
Object.defineProperty(o, k2, desc);
|
|
31
|
+
}) : (function(o, m, k, k2) {
|
|
32
|
+
if (k2 === undefined) k2 = k;
|
|
33
|
+
o[k2] = m[k];
|
|
34
|
+
}));
|
|
35
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
36
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
37
|
+
}) : function(o, v) {
|
|
38
|
+
o["default"] = v;
|
|
39
|
+
});
|
|
40
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
41
|
+
var ownKeys = function(o) {
|
|
42
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
43
|
+
var ar = [];
|
|
44
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
45
|
+
return ar;
|
|
46
|
+
};
|
|
47
|
+
return ownKeys(o);
|
|
48
|
+
};
|
|
49
|
+
return function (mod) {
|
|
50
|
+
if (mod && mod.__esModule) return mod;
|
|
51
|
+
var result = {};
|
|
52
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
53
|
+
__setModuleDefault(result, mod);
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
})();
|
|
57
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
|
+
exports.getConfig = getConfig;
|
|
59
|
+
exports.configureAndroid = configureAndroid;
|
|
60
|
+
exports.configureIOS = configureIOS;
|
|
61
|
+
exports.configureWeb = configureWeb;
|
|
62
|
+
const fs = __importStar(require("fs"));
|
|
63
|
+
const path = __importStar(require("path"));
|
|
64
|
+
// Get environment variables
|
|
65
|
+
const PLUGIN_ROOT = process.cwd();
|
|
66
|
+
const CONFIG_JSON = process.env.CAPACITOR_CONFIG;
|
|
67
|
+
const PLATFORM = process.env.CAPACITOR_PLATFORM_NAME;
|
|
68
|
+
// File paths
|
|
69
|
+
const gradlePropertiesPath = path.join(PLUGIN_ROOT, 'android', 'gradle.properties');
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Logging Utilities
|
|
72
|
+
// ============================================================================
|
|
73
|
+
const colors = {
|
|
74
|
+
reset: '\x1b[0m',
|
|
75
|
+
bright: '\x1b[1m',
|
|
76
|
+
green: '\x1b[32m',
|
|
77
|
+
red: '\x1b[31m',
|
|
78
|
+
yellow: '\x1b[33m',
|
|
79
|
+
blue: '\x1b[34m',
|
|
80
|
+
cyan: '\x1b[36m',
|
|
81
|
+
gray: '\x1b[90m',
|
|
82
|
+
};
|
|
83
|
+
function log(message, emoji = '', color = '') {
|
|
84
|
+
const emojiPart = emoji ? `${emoji} ` : '';
|
|
85
|
+
const colorCode = color || colors.reset;
|
|
86
|
+
const resetCode = color ? colors.reset : '';
|
|
87
|
+
console.log(`${colorCode}${emojiPart}${message}${resetCode}`);
|
|
88
|
+
}
|
|
89
|
+
function logSuccess(message) {
|
|
90
|
+
log(message, '✔', colors.green);
|
|
91
|
+
}
|
|
92
|
+
function logError(message) {
|
|
93
|
+
log(message, '✖', colors.red);
|
|
94
|
+
}
|
|
95
|
+
function logInfo(message) {
|
|
96
|
+
log(message, 'ℹ', colors.blue);
|
|
97
|
+
}
|
|
98
|
+
function logWarning(message) {
|
|
99
|
+
log(message, '⚠', colors.yellow);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Parse NativeAudio configuration from Capacitor config
|
|
103
|
+
* Default: hls = true (for backward compatibility)
|
|
104
|
+
*/
|
|
105
|
+
function getConfig() {
|
|
106
|
+
const defaultConfig = {
|
|
107
|
+
hls: true, // Enabled by default for backward compatibility
|
|
108
|
+
};
|
|
109
|
+
try {
|
|
110
|
+
if (!CONFIG_JSON) {
|
|
111
|
+
logInfo('No CAPACITOR_CONFIG found, using defaults (HLS enabled)');
|
|
112
|
+
return defaultConfig;
|
|
113
|
+
}
|
|
114
|
+
const config = JSON.parse(CONFIG_JSON);
|
|
115
|
+
const nativeAudioConfig = config.plugins?.NativeAudio || {};
|
|
116
|
+
return {
|
|
117
|
+
hls: nativeAudioConfig.hls !== false, // Default to true unless explicitly set to false
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
logError(`Error parsing config: ${error.message}`);
|
|
122
|
+
return defaultConfig;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Log the current configuration status
|
|
127
|
+
*/
|
|
128
|
+
function logConfig(config) {
|
|
129
|
+
log('\nNativeAudio configuration:', '', colors.bright);
|
|
130
|
+
if (config.hls) {
|
|
131
|
+
console.log(` ${colors.green}✔${colors.reset} ${colors.bright}HLS (m3u8)${colors.reset}: ${colors.green}enabled${colors.reset} (includes media3-exoplayer-hls, adds ~4MB to APK)`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(` ${colors.yellow}○${colors.reset} ${colors.bright}HLS (m3u8)${colors.reset}: ${colors.yellow}disabled${colors.reset} (reduces APK size by ~4MB)`);
|
|
135
|
+
}
|
|
136
|
+
console.log('');
|
|
137
|
+
}
|
|
138
|
+
// ============================================================================
|
|
139
|
+
// Android: Gradle Configuration
|
|
140
|
+
// ============================================================================
|
|
141
|
+
/**
|
|
142
|
+
* Write gradle.properties file for Android
|
|
143
|
+
* Injects NativeAudio properties while preserving existing content
|
|
144
|
+
*/
|
|
145
|
+
function configureAndroid(config) {
|
|
146
|
+
logInfo('Configuring Android dependencies...');
|
|
147
|
+
try {
|
|
148
|
+
// Read existing gradle.properties if it exists
|
|
149
|
+
let existingContent = '';
|
|
150
|
+
if (fs.existsSync(gradlePropertiesPath)) {
|
|
151
|
+
existingContent = fs.readFileSync(gradlePropertiesPath, 'utf8');
|
|
152
|
+
}
|
|
153
|
+
// Remove existing NativeAudio properties (if any)
|
|
154
|
+
const lines = existingContent.split('\n');
|
|
155
|
+
const filteredLines = [];
|
|
156
|
+
let inNativeAudioSection = false;
|
|
157
|
+
let lastWasEmpty = false;
|
|
158
|
+
for (const line of lines) {
|
|
159
|
+
// Check if this is a NativeAudio property or comment
|
|
160
|
+
if (line.trim().startsWith('# NativeAudio') ||
|
|
161
|
+
line.trim().startsWith('nativeAudio.') ||
|
|
162
|
+
line.trim() === '# Generated by NativeAudio hook script') {
|
|
163
|
+
inNativeAudioSection = true;
|
|
164
|
+
continue; // Skip this line
|
|
165
|
+
}
|
|
166
|
+
// If we were in NativeAudio section and hit a non-empty line, we're done
|
|
167
|
+
if (inNativeAudioSection && line.trim() !== '') {
|
|
168
|
+
inNativeAudioSection = false;
|
|
169
|
+
}
|
|
170
|
+
// Add non-NativeAudio lines, but avoid multiple consecutive empty lines
|
|
171
|
+
if (!inNativeAudioSection) {
|
|
172
|
+
if (line.trim() === '') {
|
|
173
|
+
if (!lastWasEmpty) {
|
|
174
|
+
filteredLines.push(line);
|
|
175
|
+
lastWasEmpty = true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
filteredLines.push(line);
|
|
180
|
+
lastWasEmpty = false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// Build new NativeAudio properties section
|
|
185
|
+
const nativeAudioProperties = [];
|
|
186
|
+
nativeAudioProperties.push('');
|
|
187
|
+
nativeAudioProperties.push('# NativeAudio Optional Dependencies (auto-generated)');
|
|
188
|
+
nativeAudioProperties.push('# Generated by NativeAudio hook script');
|
|
189
|
+
nativeAudioProperties.push(`nativeAudio.hls.include=${config.hls ? 'true' : 'false'}`);
|
|
190
|
+
// Combine: existing content + new NativeAudio properties
|
|
191
|
+
const newContent = filteredLines.join('\n') + '\n' + nativeAudioProperties.join('\n') + '\n';
|
|
192
|
+
fs.writeFileSync(gradlePropertiesPath, newContent, 'utf8');
|
|
193
|
+
logSuccess('Updated gradle.properties');
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
logError(`Error updating gradle.properties: ${error.message}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// ============================================================================
|
|
200
|
+
// iOS: No Configuration Needed (yet)
|
|
201
|
+
// ============================================================================
|
|
202
|
+
/**
|
|
203
|
+
* iOS platform - HLS is handled natively by AVPlayer
|
|
204
|
+
*/
|
|
205
|
+
function configureIOS() {
|
|
206
|
+
logInfo('iOS uses native AVPlayer for HLS - no additional configuration needed');
|
|
207
|
+
}
|
|
208
|
+
// ============================================================================
|
|
209
|
+
// Web: No Configuration Needed
|
|
210
|
+
// ============================================================================
|
|
211
|
+
/**
|
|
212
|
+
* Web platform doesn't need native dependency configuration
|
|
213
|
+
*/
|
|
214
|
+
function configureWeb() {
|
|
215
|
+
logInfo('Web platform - no native dependency configuration needed');
|
|
216
|
+
}
|
|
217
|
+
// ============================================================================
|
|
218
|
+
// Main Execution
|
|
219
|
+
// ============================================================================
|
|
220
|
+
function main() {
|
|
221
|
+
const config = getConfig();
|
|
222
|
+
switch (PLATFORM) {
|
|
223
|
+
case 'android':
|
|
224
|
+
log('Configuring optional dependencies for NativeAudio', '🔧', colors.cyan);
|
|
225
|
+
logConfig(config);
|
|
226
|
+
configureAndroid(config);
|
|
227
|
+
logSuccess('Configuration complete\n');
|
|
228
|
+
break;
|
|
229
|
+
case 'ios':
|
|
230
|
+
log('Configuring NativeAudio for iOS', '🔧', colors.cyan);
|
|
231
|
+
logConfig(config);
|
|
232
|
+
configureIOS();
|
|
233
|
+
logSuccess('Configuration complete\n');
|
|
234
|
+
break;
|
|
235
|
+
case 'web':
|
|
236
|
+
configureWeb();
|
|
237
|
+
break;
|
|
238
|
+
default:
|
|
239
|
+
// If platform is not specified, configure all platforms (backward compatibility)
|
|
240
|
+
log('Configuring optional dependencies for NativeAudio', '🔧', colors.blue);
|
|
241
|
+
logConfig(config);
|
|
242
|
+
logWarning(`Unknown platform: ${PLATFORM || 'undefined'}, configuring Android`);
|
|
243
|
+
configureAndroid(config);
|
|
244
|
+
logSuccess('Configuration complete\n');
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Run if executed directly
|
|
249
|
+
if (require.main === module) {
|
|
250
|
+
main();
|
|
251
|
+
}
|