WMartin WMartin - 1 month ago 34
C# Question

Xamarin iOS native binding with JWPlayer SDK - unrecognized selector exception

What I'm Trying To Do:

Create a binding library in

Xamarin
to use the native
JWPlayer
SDK for iOS

How I Went About It:

I downloaded the
JWPlayer
iOS SDK and followed
Xamarin
's binding walkthrough using objective sharpie to create the API definitions. I then created a single page app project in
Xamarin
to add a simple
JWPlayer
player to my
viewcontroller
's view by trying to mimic
JWPlayers
developer guide for basic embedding.

The Problem

The binding project built just fine and intellisense worked for all the JWPlayer classes so I thought I did everything okay but at runtime I got the following
Foundation.MonoTouchException:



"Objective-C exception thrown. Name: NSInvalidArgumentException
Reason: -[JWConfig xmlPlayList]: unrecognized selector sent to
instance..."


If I don't load the config to the player then I can instantiate the objects just fine, but almost all the player's properties are null including it's view which is kind of necessary to add it to the main view.

Almost all the solutions to similar problems point to either an incorrect capitalization of the Export selector or a missing Export statement, neither of which appear to be the problem with my project.

Note: I don't know if it matters or not but I'm running this on a physical device (iphone 6) because the simulator caused a "the native class hasn't been loaded" exception.

The Code

Full project can be found at https://github.com/WM175309/JWPlayerBindingTest_iOS

ViewController.cs

...
public override void ViewDidLoad()
{
base.ViewDidLoad();

JWConfig config = new JWConfig("http://content.jwplatform.com/videos/f3FPINhF.mp4");
config.Size = new CoreGraphics.CGSize(100, 100);

JWPlayerController player = new JWPlayerController(config);

this.View.AddSubview(player.View);

}
...


JWPlayerController.g.cs (error thrown in the if(IsDirectBinding) scope)

...
[Export ("initWithConfig:")]
[CompilerGenerated]
public JWPlayerController (JWConfig config)
: base (NSObjectFlag.Empty)
{
if (config == null)
throw new ArgumentNullException ("config");
IsDirectBinding = GetType ().Assembly == global::ApiDefinition.Messaging.this_assembly;
if (IsDirectBinding) {
InitializeHandle (global::ApiDefinition.Messaging.IntPtr_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle ("initWithConfig:"), config.Handle), "initWithConfig:");
} else {
InitializeHandle (global::ApiDefinition.Messaging.IntPtr_objc_msgSendSuper_IntPtr (this.SuperHandle, Selector.GetHandle ("initWithConfig:"), config.Handle), "initWithConfig:");
}
}
...


ApiDefinition.cs (int the binding project, generated by Objective Sharpie)

...
// -(instancetype)initWithConfig:(JWConfig *)config;
[Export("initWithConfig:")]
IntPtr Constructor(JWConfig config);

// -(instancetype)initWithConfig:(JWConfig *)config delegate:(id<JWPlayerDelegate>)delegate;
[Export("initWithConfig:delegate:")]
IntPtr Constructor(JWConfig config, JWPlayerDelegate @delegate);

// -(instancetype)initWithConfig:(JWConfig *)config delegate:(id<JWPlayerDelegate>)delegate drmDataSource:(id<JWDrmDataSource>)drmDataSource;
[Export("initWithConfig:delegate:drmDataSource:")]
IntPtr Constructor(JWConfig config, JWPlayerDelegate @delegate, JWDrmDataSource drmDataSource);
...


JWPlayerController.h (from the JWPlayer iOS SDK)

...
/*!
Loads a new JWConfig object into the player.
@param config COnfiguration object.
*/
- (void)loadConfig:(JWConfig *)config;
...


Can anyone offer any help on this?? Thanks for your time.

Answer

Turns out I had everything right except I was missing a *.linkwith.cs file. After looking at the amazon login bindings project found at https://github.com/mono/monotouch-bindings (provided in the comments) I copied their login-with-amazon-sdk.linkwith.cs file, renamed it to match the libJWPlayer-iOS-SDK instead, and changed the name of the .a file to match the jwplayer sdk as well and everything worked.

I went back through the Xamarin binding project walkthrough and did not find any mention of a *.linkwith.cs file so either this is a major oversight by Xamarin, or I did something wrong and the linkwith file fixed my chaos.

libJWPlayer-iOS-SDK.linkwith.cs:

using System;
using ObjCRuntime;

[assembly: LinkWith("libJWPlayer-iOS-SDK.a", LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator, Frameworks = "Security", ForceLoad = true)]
Comments