@capgo/capacitor-jw-player 0.0.1 → 0.0.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/CapgoCapacitorJwPlayer.podspec +3 -1
- package/Package.swift +12 -2
- package/android/build.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +5 -0
- package/android/src/main/java/ee/forgr/capacitor_jw_player/CastOptionsProvider.java +35 -0
- package/android/src/main/java/ee/forgr/capacitor_jw_player/JwPlayerPlugin.java +1 -0
- package/android/src/main/java/ee/forgr/capacitor_jw_player/PlayerActivity.java +9 -1
- package/ios/Sources/JwPlayerPlugin/JwPlayerPlugin.swift +105 -3
- package/package.json +5 -5
|
@@ -13,6 +13,8 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
14
|
s.ios.deployment_target = '14.0'
|
|
15
15
|
s.dependency 'Capacitor'
|
|
16
|
-
s.dependency 'JWPlayerKit'
|
|
16
|
+
s.dependency 'JWPlayerKit', '>= 4.0.0'
|
|
17
|
+
s.dependency 'google-cast-sdk', '>= 4.8.1'
|
|
18
|
+
s.dependency 'Protobuf', '>= 3.13'
|
|
17
19
|
s.swift_version = '5.1'
|
|
18
20
|
end
|
package/Package.swift
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// swift-tools-version: 5.9
|
|
2
2
|
import PackageDescription
|
|
3
3
|
|
|
4
|
+
struct GoogleCastMetadata {
|
|
5
|
+
static let version: String = "4.8.3"
|
|
6
|
+
static let checksum: String = "bc2c3c2434ef2895a0388ac3f16932242d3d3ac11805f810dbe7d7bce3bb27f6"
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
let package = Package(
|
|
5
10
|
name: "CapgoCapacitorJwPlayer",
|
|
6
11
|
platforms: [.iOS(.v14)],
|
|
@@ -10,8 +15,8 @@ let package = Package(
|
|
|
10
15
|
targets: ["JwPlayerPlugin"])
|
|
11
16
|
],
|
|
12
17
|
dependencies: [
|
|
13
|
-
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git",
|
|
14
|
-
.package(url: "https://github.com/jwplayer/JWPlayerKit-package.git", .upToNextMajor(from: "4.
|
|
18
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "7.2.0"),
|
|
19
|
+
.package(url: "https://github.com/jwplayer/JWPlayerKit-package.git", .upToNextMajor(from: "4.22.0"))
|
|
15
20
|
],
|
|
16
21
|
targets: [
|
|
17
22
|
.target(
|
|
@@ -22,6 +27,11 @@ let package = Package(
|
|
|
22
27
|
.product(name: "JWPlayerKit", package: "JWPlayerKit-package")
|
|
23
28
|
],
|
|
24
29
|
path: "ios/Sources/JwPlayerPlugin"),
|
|
30
|
+
.binaryTarget(
|
|
31
|
+
name: "GoogleCast",
|
|
32
|
+
url: "https://dl.google.com/dl/chromecast/sdk/ios/GoogleCastSDK-ios-\(GoogleCastMetadata.version)_dynamic.xcframework.zip",
|
|
33
|
+
checksum: GoogleCastMetadata.checksum
|
|
34
|
+
),
|
|
25
35
|
.testTarget(
|
|
26
36
|
name: "JwPlayerPluginTests",
|
|
27
37
|
dependencies: ["JwPlayerPlugin"],
|
package/android/build.gradle
CHANGED
|
@@ -62,6 +62,7 @@ dependencies {
|
|
|
62
62
|
|
|
63
63
|
implementation "com.jwplayer:jwplayer-core:$jwPlayerVersion"
|
|
64
64
|
implementation "com.jwplayer:jwplayer-common:$jwPlayerVersion"
|
|
65
|
+
implementation "com.jwplayer:jwplayer-chromecast:$jwPlayerVersion"
|
|
65
66
|
|
|
66
67
|
implementation "androidx.media3:media3-common:$media3ExoVersion"
|
|
67
68
|
implementation "androidx.media3:media3-exoplayer:$media3ExoVersion"
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
|
15
15
|
|
|
16
16
|
<application>
|
|
17
|
+
|
|
18
|
+
<meta-data
|
|
19
|
+
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
|
|
20
|
+
android:value="ee.forgr.capacitor_jw_player.CastOptionsProvider" />
|
|
21
|
+
|
|
17
22
|
<activity
|
|
18
23
|
android:name=".PlayerActivity"
|
|
19
24
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
package ee.forgr.capacitor_jw_player;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
|
|
7
|
+
import com.google.android.gms.cast.CastMediaControlIntent;
|
|
8
|
+
import com.google.android.gms.cast.LaunchOptions;
|
|
9
|
+
import com.google.android.gms.cast.framework.CastOptions;
|
|
10
|
+
import com.google.android.gms.cast.framework.OptionsProvider;
|
|
11
|
+
import com.google.android.gms.cast.framework.SessionProvider;
|
|
12
|
+
|
|
13
|
+
import java.util.List;
|
|
14
|
+
import java.util.Locale;
|
|
15
|
+
|
|
16
|
+
public class CastOptionsProvider implements OptionsProvider {
|
|
17
|
+
|
|
18
|
+
@NonNull
|
|
19
|
+
@Override
|
|
20
|
+
public CastOptions getCastOptions(@NonNull Context context) {
|
|
21
|
+
LaunchOptions launchOptions = new LaunchOptions.Builder()
|
|
22
|
+
.setLocale(Locale.US)
|
|
23
|
+
.build();
|
|
24
|
+
|
|
25
|
+
return new CastOptions.Builder()
|
|
26
|
+
.setReceiverApplicationId(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID)
|
|
27
|
+
.setLaunchOptions(launchOptions)
|
|
28
|
+
.build();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Override
|
|
32
|
+
public List<SessionProvider> getAdditionalSessionProviders(Context context) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -9,6 +9,7 @@ import com.getcapacitor.Plugin;
|
|
|
9
9
|
import com.getcapacitor.PluginCall;
|
|
10
10
|
import com.getcapacitor.PluginMethod;
|
|
11
11
|
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
12
|
+
import com.google.android.gms.cast.framework.CastContext;
|
|
12
13
|
import com.jwplayer.pub.api.JWPlayer;
|
|
13
14
|
import com.jwplayer.pub.api.configuration.PlayerConfig;
|
|
14
15
|
import com.jwplayer.pub.api.license.LicenseUtil;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package ee.forgr.capacitor_jw_player;
|
|
2
2
|
|
|
3
3
|
import android.app.Activity;
|
|
4
|
+
import android.content.Context;
|
|
4
5
|
import android.content.Intent;
|
|
5
6
|
import android.content.res.Configuration;
|
|
6
7
|
import android.graphics.Rect;
|
|
@@ -18,6 +19,11 @@ import android.widget.ImageView;
|
|
|
18
19
|
|
|
19
20
|
import androidx.appcompat.app.AppCompatActivity;
|
|
20
21
|
|
|
22
|
+
import com.google.android.gms.cast.CastMediaControlIntent;
|
|
23
|
+
import com.google.android.gms.cast.LaunchOptions;
|
|
24
|
+
import com.google.android.gms.cast.framework.CastOptions;
|
|
25
|
+
import com.google.android.gms.cast.framework.OptionsProvider;
|
|
26
|
+
import com.google.android.gms.cast.framework.SessionProvider;
|
|
21
27
|
import com.jwplayer.pub.api.JWPlayer;
|
|
22
28
|
import com.jwplayer.pub.api.PlayerState;
|
|
23
29
|
import com.jwplayer.pub.api.UiGroup;
|
|
@@ -38,6 +44,7 @@ import com.jwplayer.ui.views.ControlbarView;
|
|
|
38
44
|
|
|
39
45
|
import java.util.ArrayList;
|
|
40
46
|
import java.util.List;
|
|
47
|
+
import java.util.Locale;
|
|
41
48
|
|
|
42
49
|
public class PlayerActivity extends AppCompatActivity implements
|
|
43
50
|
VideoPlayerEvents.OnFullscreenListener,
|
|
@@ -89,6 +96,7 @@ public class PlayerActivity extends AppCompatActivity implements
|
|
|
89
96
|
mPlayer = mPlayerView.getPlayer();
|
|
90
97
|
mPlayer.registerActivityForPip(this, getSupportActionBar());
|
|
91
98
|
|
|
99
|
+
|
|
92
100
|
// Delte fullscreen button
|
|
93
101
|
ControlbarView customControlBar = mPlayerView.getControlsContainer().getControlbarView();
|
|
94
102
|
ImageView enterFullScreenButton = customControlBar.findViewById(com.longtailvideo.jwplayer.R.id.controlbar_enter_fullscreen_btn);
|
|
@@ -466,4 +474,4 @@ public class PlayerActivity extends AppCompatActivity implements
|
|
|
466
474
|
}
|
|
467
475
|
}
|
|
468
476
|
}
|
|
469
|
-
}
|
|
477
|
+
}
|
|
@@ -2,7 +2,7 @@ import Foundation
|
|
|
2
2
|
import Capacitor
|
|
3
3
|
import JWPlayerKit
|
|
4
4
|
import AVKit // Import AVKit for AVAudioSession
|
|
5
|
-
|
|
5
|
+
import GoogleCast
|
|
6
6
|
/**
|
|
7
7
|
* Please read the Capacitor iOS Plugin Development Guide
|
|
8
8
|
* here: https://capacitorjs.com/docs/plugins/ios
|
|
@@ -17,7 +17,7 @@ protocol CallbackHandler {
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
@objc(JwPlayerPlugin)
|
|
20
|
-
public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
20
|
+
public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin, GCKLoggerDelegate {
|
|
21
21
|
public let identifier = "JwPlayerPlugin"
|
|
22
22
|
public let jsName = "JwPlayer"
|
|
23
23
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
@@ -48,6 +48,8 @@ public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
48
48
|
override public func load() {
|
|
49
49
|
// Configure the audio session when the plugin loads
|
|
50
50
|
setupAudioSession()
|
|
51
|
+
print("[JWPlayer] Plugin loaded. Note: Chromecast is initialized in AppDelegate.")
|
|
52
|
+
initializeChromecast()
|
|
51
53
|
super.load()
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -63,6 +65,32 @@ public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
private func initializeChromecast() {
|
|
69
|
+
print("[ChromecastDebug] Starting Chromecast initialization")
|
|
70
|
+
let kReceiverAppID = "CC1AD845" // Custom App ID for Chromecast
|
|
71
|
+
let discoveryCriteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
|
|
72
|
+
let options = GCKCastOptions(discoveryCriteria: discoveryCriteria)
|
|
73
|
+
options.physicalVolumeButtonsWillControlDeviceVolume = true
|
|
74
|
+
options.disableDiscoveryAutostart = false
|
|
75
|
+
print("[ChromecastDebug] Setting custom options for Chromecast")
|
|
76
|
+
do {
|
|
77
|
+
GCKCastContext.setSharedInstanceWith(options)
|
|
78
|
+
print("[ChromecastDebug] Chromecast context initialized with App ID: \(kReceiverAppID)")
|
|
79
|
+
} catch {
|
|
80
|
+
print("[ChromecastDebug] Error initializing Chromecast context: \(error.localizedDescription)")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let filter = GCKLoggerFilter.init()
|
|
84
|
+
filter.minimumLevel = .verbose
|
|
85
|
+
GCKLogger.sharedInstance().filter = filter
|
|
86
|
+
GCKLogger.sharedInstance().delegate = self
|
|
87
|
+
print("[ChromecastDebug] Logger initialized")
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) {
|
|
91
|
+
print(function + " - " + message)
|
|
92
|
+
}
|
|
93
|
+
|
|
66
94
|
@objc func initialize(_ call: CAPPluginCall) {
|
|
67
95
|
print("[JWPlayer] initialize called")
|
|
68
96
|
guard let licenseKey = call.getString("licenseKey") else {
|
|
@@ -612,7 +640,6 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
612
640
|
print("[JWPlayer] Configuring player from init config")
|
|
613
641
|
player.configurePlayer(with: config)
|
|
614
642
|
print("[JWPlayer] Player configured successfully from init config")
|
|
615
|
-
|
|
616
643
|
} else {
|
|
617
644
|
print("[JWPlayer] Error: Player configuration is missing in viewDidLoad")
|
|
618
645
|
self.callbackHandler?.notifyEventListener("error", data: ["message": "Player configuration missing"])
|
|
@@ -746,4 +773,79 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
746
773
|
callbackHandler?.onPlayerDismissed(isPiPDismissal: false)
|
|
747
774
|
}
|
|
748
775
|
}
|
|
776
|
+
|
|
777
|
+
// MARK: - JWCastDelegate
|
|
778
|
+
// Optionally, override the following methods to receive and respond to events when casting.
|
|
779
|
+
// Always call the superclass's method when overriding these methods.
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
// Called when a new casting device comes online.
|
|
783
|
+
override func castController(_ controller: JWCastController, devicesAvailable devices: [JWCastingDevice]) {
|
|
784
|
+
super.castController(controller, devicesAvailable: devices)
|
|
785
|
+
print("[JWCastDelegate]: \(devices.count) became available: \(devices)")
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Called when a successful connection to a casting device is made.
|
|
789
|
+
override func castController(_ controller: JWCastController, connectedTo device: JWCastingDevice) {
|
|
790
|
+
super.castController(controller, connectedTo: device)
|
|
791
|
+
print("[JWCastDelegate]: Connected to device: \(device.identifier)")
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
// Called when the casting device disconnects.
|
|
796
|
+
override func castController(_ controller: JWCastController, disconnectedWithError error: Error?) {
|
|
797
|
+
super.castController(controller, disconnectedWithError: error)
|
|
798
|
+
|
|
799
|
+
if let error {
|
|
800
|
+
print("[JWCastDelegate]: Casting disconnected from device with error: \"\(error.localizedDescription)\"")
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
print("[JWCastDelegate]: Casting disconnected from device successfully.")
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
// Called when the connected casting device is temporarily disconnected. Video resumes on the mobile device until connection resumes.
|
|
809
|
+
override func castController(_ controller: JWCastController, connectionSuspendedWithDevice device: JWCastingDevice) {
|
|
810
|
+
super.castController(controller, connectionSuspendedWithDevice: device)
|
|
811
|
+
print("[JWCastDelegate]: Connection suspended with device: \(device.identifier)")
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
// Called after connection is reestablished following a temporary disconnection. Video resumes on the casting device.
|
|
816
|
+
override func castController(_ controller: JWCastController, connectionRecoveredWithDevice device: JWCastingDevice) {
|
|
817
|
+
super.castController(controller, connectionRecoveredWithDevice: device)
|
|
818
|
+
print("[JWCastDelegate]: Connection recovered with device: \(device.identifier)")
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// Called when an attempt to connect to a casting device is unsuccessful.
|
|
822
|
+
override func castController(_ controller: JWCastController, connectionFailedWithError error: Error) {
|
|
823
|
+
super.castController(controller, connectionFailedWithError: error)
|
|
824
|
+
print("[JWCastDelegate]: Connection failed with error: \(error.localizedDescription)")
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// Called when casting session begins.
|
|
828
|
+
override func castController(_ controller: JWCastController, castingBeganWithDevice device: JWCastingDevice) {
|
|
829
|
+
super.castController(controller, castingBeganWithDevice: device)
|
|
830
|
+
print("[JWCastDelegate]: Casting began with device: \(device.identifier)")
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// Called when an attempt to cast to a casting device is unsuccessful.
|
|
834
|
+
override func castController(_ controller: JWCastController, castingFailedWithError error: Error) {
|
|
835
|
+
super.castController(controller, castingFailedWithError: error)
|
|
836
|
+
print("[JWCastDelegate]: Casting failed with error: \(error.localizedDescription)")
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// Called when a casting session ends.
|
|
840
|
+
override func castController(_ controller: JWCastController, castingEndedWithError error: Error?) {
|
|
841
|
+
super.castController(controller, castingEndedWithError: error)
|
|
842
|
+
|
|
843
|
+
if let error {
|
|
844
|
+
print("[JWCastDelegate]: Casting ended with error: \"\(error.localizedDescription)\"")
|
|
845
|
+
}
|
|
846
|
+
else {
|
|
847
|
+
print("[JWCastDelegate]: Casting ended successfully.")
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
749
851
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-jw-player",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Playes videos from jwplayer.com",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"prepublishOnly": "npm run build"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@capacitor/android": "^7.
|
|
50
|
-
"@capacitor/core": "^7.
|
|
49
|
+
"@capacitor/android": "^7.2.0",
|
|
50
|
+
"@capacitor/core": "^7.2.0",
|
|
51
51
|
"@capacitor/docgen": "^0.3.0",
|
|
52
|
-
"@capacitor/ios": "^7.
|
|
52
|
+
"@capacitor/ios": "^7.2.0",
|
|
53
53
|
"@ionic/eslint-config": "^0.4.0",
|
|
54
54
|
"@ionic/prettier-config": "^4.0.0",
|
|
55
55
|
"@ionic/swiftlint-config": "^2.0.0",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"typescript": "~4.1.5"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@capacitor/core": ">=7.
|
|
65
|
+
"@capacitor/core": ">=7.2.0"
|
|
66
66
|
},
|
|
67
67
|
"prettier": "@ionic/prettier-config",
|
|
68
68
|
"swiftlint": "@ionic/swiftlint-config",
|