Skip to content

Instantly share code, notes, and snippets.

@felipeska
Forked from brendanzagaeski/Metadata.xml
Created May 29, 2019 19:49
Show Gist options
  • Save felipeska/26be01c7c9f1f3b52e723965f1c411e7 to your computer and use it in GitHub Desktop.
Save felipeska/26be01c7c9f1f3b52e723965f1c411e7 to your computer and use it in GitHub Desktop.
Some Metadata.xml fixes for binding the Socialize Android SDK (http://getsocialize.com/sdk/) in Xamarin.Android
<metadata>
<!-- Some Metadata.xml fixes for binding the Socialize Android SDK (http://getsocialize.com/sdk/) in Xamarin.Android
Note that this is not a complete set of fixes. These changes only address the first round of compile errors. -->
<!-- Fixes for duplicate EventArgs, as discussed on:
http://docs.xamarin.com/guides/android/advanced_topics/java_integration_overview/binding_a_java_library_(.jar)/#Problem_Duplicate_custom_EventArgs_types
Error message: Error CS0102: The type `SomeClass` already contains a definition for `p0' (CS0102) -->
<attr path="/api/package[@name='com.socialize.auth.twitter']/interface[@name='TwitterAuthListener']/method[@name='onError' and count(parameter)=1 and parameter[1][@type='com.socialize.error.SocializeException']]" name="argsType">AuthTwitterErrorEventArgs</attr>
<attr path="/api/package[@name='com.socialize.facebook']/interface[@name='Facebook.DialogListener']/method[@name='onComplete' and count(parameter)=1 and parameter[1][@type='android.os.Bundle']]" name="argsType">SocializeFacebookCompleteEventArgs</attr>
<attr path="/api/package[@name='com.socialize.facebook']/interface[@name='Facebook.DialogListener']/method[@name='onError' and count(parameter)=1 and parameter[1][@type='com.socialize.facebook.DialogError']]" name="argsType">SocializeFacebookErrorEventArgs</attr>
<attr path="/api/package[@name='com.socialize.facebook']/interface[@name='Facebook.DialogListener']/method[@name='onFacebookError' and count(parameter)=1 and parameter[1][@type='com.socialize.facebook.FacebookError']]" name="argsType">SocializeFacebookFacebookErrorEventArgs</attr>
<!-- Fixes for duplicate event handler method names because `Com.Socialize.Socialize` implements both
`Com.Socialize.UI.ISocializeActivityLifecycleListener` and `Com.Socialize.ISocializeLifecycleListener`
Error message: Error CS0102: The type `SomeClass' already contains a definition for `SomeEventName' (CS0102) -->
<attr path="/api/package[@name='com.socialize.ui']/interface[@name='SocializeActivityLifecycleListener']/method[@name='onCreate' and count(parameter)=2 and parameter[1][@type='com.socialize.ui.SocializeUIActivity'] and parameter[2][@type='android.os.Bundle']]" name="managedName">UICreate</attr>
<attr path="/api/package[@name='com.socialize.ui']/interface[@name='SocializeActivityLifecycleListener']/method[@name='onDestroy' and count(parameter)=1 and parameter[1][@type='com.socialize.ui.SocializeUIActivity']]" name="managedName">UIDestroy</attr>
<attr path="/api/package[@name='com.socialize.ui']/interface[@name='SocializeActivityLifecycleListener']/method[@name='onPause' and count(parameter)=1 and parameter[1][@type='com.socialize.ui.SocializeUIActivity']]" name="managedName">UIPause</attr>
<attr path="/api/package[@name='com.socialize.ui']/interface[@name='SocializeActivityLifecycleListener']/method[@name='onResume' and count(parameter)=1 and parameter[1][@type='com.socialize.ui.SocializeUIActivity']]" name="managedName">UIResume</attr>
<!-- Due to limited Java generics support (http://docs.xamarin.com/guides/android/advanced_topics/limitations/#Partial_Java_Generics_Support),
the `Params...` version and the `java.lang.Object...` version collide.
Error message: Error CS0111: A member `SomeMethodName' is already defined. Rename this member or use different parameter types (CS0111) -->
<remove-node path="/api/package[@name='com.socialize.api']/class[@name='SocializeApi.AbstractAsyncProcess']/method[@name='doInBackground' and count(parameter)=1 and parameter[1][@type='Params...']]" />
<!-- Same problem here, except that in this case the type parameter is named `Result` -->
<remove-node path="/api/package[@name='com.socialize.api']/class[@name='SocializeApi.AbstractAsyncProcess']/method[@name='onPostExecuteManaged' and count(parameter)=1 and parameter[1][@type='Result']]" />
<!-- Fixes for several cases where the original generic return type is automatically "simplified" to `java.lang.Object`.
Error message: Error CS0508: `SomeMethodName` return type must be `Java.Lang.Object' to match overridden member `SomeMethodName` (CS0508) -->
<attr path="/api/package[@name='com.socialize.auth.facebook']/class[@name='FacebookAuthProviderInfoFactory']/method[@name='initInstanceForRead' and count(parameter)=1 and parameter[1][@type='java.lang.String...']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth.facebook']/class[@name='FacebookAuthProviderInfoFactory']/method[@name='initInstanceForWrite' and count(parameter)=1 and parameter[1][@type='java.lang.String...']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth']/class[@name='SocializeAuthProviderInfoFactory']/method[@name='initInstanceForRead' and count(parameter)=1 and parameter[1][@type='java.lang.String...']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth']/class[@name='SocializeAuthProviderInfoFactory']/method[@name='initInstanceForWrite' and count(parameter)=1 and parameter[1][@type='java.lang.String...']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth.twitter']/class[@name='TwitterAuthProviderInfoFactory']/method[@name='initInstanceForRead' and count(parameter)=1 and parameter[1][@type='java.lang.String...']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth.twitter']/class[@name='TwitterAuthProviderInfoFactory']/method[@name='initInstanceForWrite' and count(parameter)=1 and parameter[1][@type='java.lang.String...']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.notifications']/class[@name='SimpleNotificationMessageTranslator']/method[@name='translate' and count(parameter)=2 and parameter[1][@type='android.content.Context'] and parameter[2][@type='com.socialize.notifications.NotificationMessage']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.ui.view']/class[@name='LoadingItemView']/method[@name='createMainView' and count(parameter)=0]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.ui.view']/class[@name='LoadingListView']/method[@name='createMainView' and count(parameter)=0]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeApi.AsyncAuthenicator']/method[@name='doInBackground' and count(parameter)=1 and parameter[1][@type='com.socialize.api.SocializeRequest']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeApi.AsyncGetter']/method[@name='doInBackground' and count(parameter)=1 and parameter[1][@type='com.socialize.api.SocializeRequest']]" name="managedReturn">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeApi.AsyncPutter']/method[@name='doInBackground' and count(parameter)=1 and parameter[1][@type='com.socialize.api.SocializeRequest']]" name="managedReturn">Java.Lang.Object</attr>
<!-- There are a few more of the simplified `java.lang.Object` cases in the "internal" namespaces, but since those
are "internal," we can just remove them completely -->
<remove-node path="/api/package[starts-with(@name, 'com.socialize.google.gson.internal')]" />
<!-- There are also some cases where the return type on an interface is simplified to a non-generic collection
type, so the implementing class must likewise simplify the return type to the non-generic version.
Error message: Error CS0738: `SomeClass' does not implement interface member `SomeInterface.SomeMethod()' and the best implementing candidate `SomeClass.SomeMethod()' return type `System.Collections.Generic.ICollection<SomeJavaType>' does not match interface member return type `System.Collections.ICollection' (CS0738)
## Specific example
Error message: Error CS0738: `Com.Socialize.Oauth.Signpost.Http.HttpParameters' does not implement interface member `Java.Util.IMap.EntrySet()' and the best implementing candidate `Com.Socialize.Oauth.Signpost.Http.HttpParameters.EntrySet()' return type `System.Collections.Generic.ICollection<Java.Util.IMapEntry>' does not match interface member return type `System.Collections.ICollection' (CS0738)
Changing the `managedReturn` will result in a secondary error:
Error CS0266: Cannot implicitly convert type `System.Collections.Generic.ICollection<Java.Util.IMapEntry>' to `System.Collections.ICollection'. An explicit conversion exists (are you missing a cast?) (CS0266)
So instead we can change the `return` attribute. As long as this does not change the JNI signature of the
method, it should not cause any problems. See also the description of `managedReturn` on:
http://docs.xamarin.com/guides/android/advanced_topics/java_integration_overview/binding_a_java_library_(.jar)/api_metadata_reference/#Supported_Attributes -->
<attr path="/api/package[@name='com.socialize.oauth.signpost.http']/class[@name='HttpParameters']/method[@name='entrySet' and count(parameter)=0]" name="return">java.util.Set</attr>
<!-- The bindings generator does not currently handle cases where a subclass provides an abstract override for an
abstract method. From what I've seen, there is no need to keep abstract overrides of abstract methods in the
binding, so we can remove them.
Error message: Error CS0533: `SomeMethodName' hides inherited abstract member `SomeMethodName' (CS0533) -->
<remove-node path="/api/package[@name='com.socialize.entity']/class[@name='SocializeActionFactory']/method[@name='postFromJSON' and count(parameter)=2 and parameter[1][@type='org.json.JSONObject'] and parameter[2][@type='T']]" />
<remove-node path="/api/package[@name='com.socialize.entity']/class[@name='SocializeActionFactory']/method[@name='postToJSON' and count(parameter)=2 and parameter[1][@type='T'] and parameter[2][@type='org.json.JSONObject']]" />
<!-- There are also some methods that need to have their generic _parameter_ types simplified to `java.lang.Object`.
Possible error message: Error CS0115: `SomeMethod(..., T, ...)' is marked as an override but no suitable method found to override (CS0115)
Possible error message: Error CS0535: `SomeClass' does not implement interface member `SomeMethod(..., Java.Lang.Object,...)' (CS0535)
Possible error message: Error CS0534: `SomeClass' does not implement inherited abstract member `SomeMethod(..., Java.Lang.Object,...)' (CS0534) -->
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeApi.AsyncAuthenicator']/method[@name='doInBackground' and count(parameter)=1 and parameter[1][@type='com.socialize.api.SocializeRequest']]/parameter[1]" name="managedType">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeApi.AsyncGetter']/method[@name='doInBackground' and count(parameter)=1 and parameter[1][@type='com.socialize.api.SocializeRequest']]/parameter[1]" name="managedType">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeApi.AsyncPutter']/method[@name='doInBackground' and count(parameter)=1 and parameter[1][@type='com.socialize.api.SocializeRequest']]/parameter[1]" name="managedType">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.api.action.share']/class[@name='SocialNetworkDialogListener']/method[@name='onShow' and count(parameter)=2 and parameter[1][@type='android.app.Dialog'] and parameter[2][@type='com.socialize.ui.share.SharePanelView']]/parameter[2]" name="managedType">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth.facebook']/class[@name='FacebookAuthProviderInfoFactory']/method[@name='updateForRead' and count(parameter)=2 and parameter[1][@type='com.socialize.auth.facebook.FacebookAuthProviderInfo'] and parameter[2][@type='java.lang.String...']]/parameter[1]" name="managedType">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth.facebook']/class[@name='FacebookAuthProviderInfoFactory']/method[@name='updateForWrite' and count(parameter)=2 and parameter[1][@type='com.socialize.auth.facebook.FacebookAuthProviderInfo'] and parameter[2][@type='java.lang.String...']]/parameter[1]" name="managedType">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth']/class[@name='SocializeAuthProviderInfoFactory']/method[@name='updateForRead' and count(parameter)=2 and parameter[1][@type='com.socialize.auth.SocializeAuthProviderInfo'] and parameter[2][@type='java.lang.String...']]/parameter[1]" name="managedType">Java.Lang.Object</attr>
<attr path="/api/package[@name='com.socialize.auth']/class[@name='SocializeAuthProviderInfoFactory']/method[@name='updateForWrite' and count(parameter)=2 and parameter[1][@type='com.socialize.auth.SocializeAuthProviderInfo'] and parameter[2][@type='java.lang.String...']]/parameter[1]" name="managedType">Java.Lang.Object</attr>
<!-- Sometimes the inherited interface only has a `set` method, with no corresponding `get` method, but the
inheriting class implements both. One option would be to convert the setters on the interfaces to properties. The
other option would be to convert the properties on the class to methods. The story here is actually a bit more
complicated because the setters are defined in one interface, and the getters are in another. To make things
a little easier to follow, we'll just use plain methods for everything.
Possible error message: Error CS0535: `SomeClass' does not implement interface member `SomeMethod' (CS0535) -->
<attr path="/api/package[@name='com.socialize.api']/interface[@name='SocializeSession']/method[starts-with(@name, 'get')]" name="propertyName"></attr>
<attr path="/api/package[@name='com.socialize.oauth']/interface[@name='OAuthAuthorizer']/method[starts-with(@name, 'getConsumerToken')]" name="propertyName"></attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeSessionImpl']/method[starts-with(@name, 'get')]" name="propertyName"></attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeSessionImpl']/method[starts-with(@name, 'set')]" name="propertyName"></attr>
<!-- If you didn't want to prevent _all_ of the `get*` and `set*` methods in `SocializeSessionImpl` from becoming
properties, you could use individual XPaths instead. For example:
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeSessionImpl']/method[@name='getConsumerKey' and count(parameter)=0]" name="propertyName"></attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeSessionImpl']/method[@name='setConsumerKey' and count(parameter)=1 and parameter[1][@type='java.lang.String']]" name="propertyName"></attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeSessionImpl']/method[@name='getConsumerToken' and count(parameter)=0]" name="propertyName"></attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeSessionImpl']/method[@name='setConsumerToken' and count(parameter)=1 and parameter[1][@type='java.lang.String']]" name="propertyName"></attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeSessionImpl']/method[@name='getConsumerTokenSecret' and count(parameter)=0]" name="propertyName"></attr>
<attr path="/api/package[@name='com.socialize.api']/class[@name='SocializeSessionImpl']/method[@name='setConsumerTokenSecret' and count(parameter)=1 and parameter[1][@type='java.lang.String']]" name="propertyName"></attr>-->
<!-- `Handle` is a reserved word in Xamarin.Android bindings projects, so rename the `Handle` methods to avoid a
conflict.
Possible error message: Error CS0019: Operator `!=' cannot be applied to operands of type `method group' and `System.IntPtr' (CS0019)
Possible error message: Error CS1502: The best overloaded method match for `Android.Runtime.JNIEnv.FinishCreateInstance(System.IntPtr, string, params Android.Runtime.JValue[])' has some invalid arguments (CS1502)
Possible error message: Error CS1503: Argument `#1' cannot convert `method group' expression to type `System.IntPtr' (CS1503) -->
<attr path="/api/package[@name='com.socialize.share']/interface[@name='ShareHandler']/method[@name='handle']" name="managedName">HandleShare</attr>
<attr path="/api/package[@name='com.socialize.share']/class[@name='AbstractShareHandler']/method[@name='handle']" name="managedName">HandleShare</attr>
<attr path="/api/package[@name='com.socialize.share']/class[@name='EmailShareHandler']/method[@name='handle']" name="managedName">HandleShare</attr>
<attr path="/api/package[@name='com.socialize.share']/class[@name='FacebookShareHandler']/method[@name='handle']" name="managedName">HandleShare</attr>
<attr path="/api/package[@name='com.socialize.share']/class[@name='GooglePlusShareHandler']/method[@name='handle']" name="managedName">HandleShare</attr>
<attr path="/api/package[@name='com.socialize.share']/class[@name='SmsShareHandler']/method[@name='handle']" name="managedName">HandleShare</attr>
<attr path="/api/package[@name='com.socialize.share']/class[@name='TwitterShareHandler']/method[@name='handle']" name="managedName">HandleShare</attr>
<!-- Error message: Error CS1061: Type `SomeClass' does not contain a definition for `Handler' and no extension method `Handler' of type `SomeInheritedInterface' could be found. Are you missing an assembly reference? (CS1061)
Error message: Error CS1729: The type `SomeClass` does not contain a constructor that takes `0' arguments (CS1729)
https://bugzilla.xamarin.com/show_bug.cgi?id=17788
The best workaround in this case is unfortunately tricky because this is a bug in the bindings generator. One
way to stop the problem is to remove the `OnCreateDialog()` member from `ISocializeActivityLifecycleListener`,
but that changes the API of the interface. Similarly, you can avoid the problem by removing the
`setSocializeActivityLifecycleListener` method from `Socialize`.
If you need to use the tricky workaround, here's one way to do it:
1. Compile once with the two `remove-node` lines below commented out.
2. Save the generated `obj/Debug/generated/src/Com.Socialize.Socialize.cs` to a backup location
3. Un-comment the two `remove-node` lines, and recompile.
4. Diff the old `Com.Socialize.Socialize.cs` from step (2) against the new file from step (3)
5. Copy the lines that are present in the file from (2) but missing from (3) to a `public partial` "Socialize"
class in the `Additions` folder.
6. In the `Socialize.CreateDialog` property, change `impl.Handler` to `impl.OnCreateDialogHandler`.
7. Also change `new global::Com.Socialize.UI.ISocializeActivityLifecycleListenerImplementor()` to:
`new global::Com.Socialize.UI.ISocializeActivityLifecycleListenerImplementor(this)`.
Note that the bug has been fixed, and the fix will be released in a future version of Xamarin.Android. If you're
not in a hurry, waiting for that release would be the easiest fix of all :-) -->
<remove-node path="/api/package[@name='com.socialize']/class[@name='Socialize']/method[@name='getSocializeActivityLifecycleListener' and count(parameter)=0]" />
<remove-node path="/api/package[@name='com.socialize']/class[@name='Socialize']/method[@name='setSocializeActivityLifecycleListener' and count(parameter)=1 and parameter[1][@type='com.socialize.ui.SocializeActivityLifecycleListener']]" />
</metadata>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment