Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using Android.App;
using Android.Runtime;
using Java.Interop;

namespace Android.Gms.Games
{
public sealed partial class PlayGames
{
// Matches: getSnapshotsClient(Activity) -> SnapshotsClient
[Register("getSnapshotsClient", "(Landroid/app/Activity;)Lcom/google/android/gms/games/SnapshotsClient;", "")]
public static unsafe global::Android.Gms.Games.SnapshotsClient GetSnapshotsClient(global::Android.App.Activity activity)
{
const string __id = "getSnapshotsClient.(Landroid/app/Activity;)Lcom/google/android/gms/games/SnapshotsClient;";
try
{
JniArgumentValue* __args = stackalloc JniArgumentValue[1];
__args[0] = new JniArgumentValue((activity == null) ? IntPtr.Zero : ((global::Java.Lang.Object)activity).Handle);
var __rm = _members.StaticMethods.InvokeObjectMethod(__id, __args);
return global::Java.Lang.Object.GetObject<global::Android.Gms.Games.SnapshotsClient>(__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
}
finally
{
global::System.GC.KeepAlive(activity);
}
}
Comment on lines +11 to +26
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were these generated following .NET 10's generated code? or .NET 8/9?

.NET 10 has significate changes here to support NativeAOT.

Ideally, we could somehow make this work in Metadata.xml, as it would not need to be manually updated if we improve the generated code.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is generated only for .NET 8/9.
I tried different approaches to fix them with metadata.xml file but no luck, it just skips these Apis even if you write metadata.xml correctly, my guess is that there is a bug or limitation with Xamarin binding generator

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it print out a build warning? That could say why it skips them.

@moljac might have some suggestions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for exmaple I tried this:
<attr path="/api/package[@name='com.google.android.gms.games.snapshot']/class[@name='Snapshot']" name="visibility" value="public" />
and also this
<interface` path="/api/package[@name='com.google.android.gms.games.snapshot']/interface[@name='Snapshot']" name="Snapshot" managedName="ISnapshot" visibility="public" />

but none of them generated the snapshot class or interface and I didn't see any warning during build process

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for exmaple I tried this: <attr path="/api/package[@name='com.google.android.gms.games.snapshot']/class[@name='Snapshot']" name="visibility" value="public" />

OK this looks OK.

and also this <interface` path="/api/package[@name='com.google.android.gms.games.snapshot']/interface[@name='Snapshot']" name="Snapshot" managedName="ISnapshot" visibility="public" />

This does not make sense. This looks like api.xml snippet.

but none of them generated the snapshot class or interface and I didn't see any warning during build process

You must turn on all warnings to see what is going on. Yeah it is a bit unpractical, but 99% of those warnings will never (or optimistically not so soon) be fixed.


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.IO;
using Android.Runtime;
using Java.Interop;

namespace Android.Gms.Games.Snapshot
{
// Manual binding for com.google.android.gms.games.snapshot.Snapshot
[Register ("com/google/android/gms/games/snapshot/Snapshot", DoNotGenerateAcw = true)]
public sealed partial class Snapshot : Java.Lang.Object
{
static readonly JniPeerMembers _members =
new XAPeerMembers ("com/google/android/gms/games/snapshot/Snapshot", typeof (Snapshot));

internal Snapshot (IntPtr handle, JniHandleOwnership transfer) : base (handle, transfer) { }

public override JniPeerMembers JniPeerMembers => _members;
protected override IntPtr ThresholdClass => _members.JniPeerType.PeerReference.Handle;
protected override Type ThresholdType => _members.ManagedPeerType;

// -------------------------
// Core Java API bindings
// -------------------------

// SnapshotMetadata getMetadata()
[Register ("getMetadata", "()Lcom/google/android/gms/games/snapshot/SnapshotMetadata;", "")]
public unsafe SnapshotMetadata GetMetadata ()
{
const string __id = "getMetadata.()Lcom/google/android/gms/games/snapshot/SnapshotMetadata;";
JniArgumentValue* __args = stackalloc JniArgumentValue [0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod (__id, this, __args);
return Java.Lang.Object.GetObject<SnapshotMetadata> (__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
}

// SnapshotContents getSnapshotContents()
[Register ("getSnapshotContents", "()Lcom/google/android/gms/games/snapshot/SnapshotContents;", "")]
public unsafe SnapshotContents GetSnapshotContents ()
{
const string __id = "getSnapshotContents.()Lcom/google/android/gms/games/snapshot/SnapshotContents;";
JniArgumentValue* __args = stackalloc JniArgumentValue [0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod (__id, this, __args);
return Java.Lang.Object.GetObject<SnapshotContents> (__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
}

/// <summary>
/// Read the full byte[] contents of this snapshot.
/// </summary>
public byte [] ReadFully ()
{
var contents = GetSnapshotContents ();
return contents?.ReadFully () ?? Array.Empty<byte> ();
}

public void WriteBytes (byte [] data)
{
var contents = GetSnapshotContents ();
if (contents == null)
throw new InvalidOperationException ("SnapshotContents is null.");

if (!contents.WriteBytes (data))
throw new IOException ("Failed to write snapshot data.");
}

/// <summary>
/// Close the underlying SnapshotContents (if you want to close manually).
/// Usually CommitAndClose on SnapshotsClient is preferred.
/// </summary>
public void CloseContents ()
{
var contents = GetSnapshotContents ();
contents?.Close ();
}

// Optional: convenience property that returns SnapshotMetadata
public SnapshotMetadata Metadata => GetMetadata ();

// A small helper to get a friendly SnapshotId through metadata (returns null if metadata missing)
public string? SnapshotId => GetMetadata ()?.SnapshotId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System;
using Android.Runtime;
using Java.IO;
using Java.Interop;

namespace Android.Gms.Games.Snapshot
{
[Register("com/google/android/gms/games/snapshot/SnapshotContents", DoNotGenerateAcw = true)]
public sealed partial class SnapshotContents : Java.Lang.Object
{
static readonly JniPeerMembers _members =
new XAPeerMembers("com/google/android/gms/games/snapshot/SnapshotContents", typeof(SnapshotContents));

internal SnapshotContents(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { }

public override JniPeerMembers JniPeerMembers => _members;
protected override IntPtr ThresholdClass => _members.JniPeerType.PeerReference.Handle;
protected override Type ThresholdType => _members.ManagedPeerType;

[Register("readFully", "()[B", "")]
public unsafe byte[] ReadFully()
{
const string __id = "readFully.()[B";
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod(__id, this, null);
return (byte[])JNIEnv.GetArray(__rm.Handle, JniHandleOwnership.TransferLocalRef, typeof(byte));
}

[Register("writeBytes", "([B)Z", "")]
public unsafe bool WriteBytes(byte[] data)
{
const string __id = "writeBytes.([B)Z";
IntPtr native_data = JNIEnv.NewArray(data);
try
{
JniArgumentValue* __args = stackalloc JniArgumentValue[1];
__args[0] = new JniArgumentValue(native_data);
var __rm = _members.InstanceMethods.InvokeVirtualBooleanMethod(__id, this, __args);
return __rm;
}
finally
{
if (data != null)
{
JNIEnv.CopyArray(native_data, data);
JNIEnv.DeleteLocalRef(native_data);
}
}
}

[Register("close", "()V", "")]
public unsafe void Close()
{
const string __id = "close.()V";
_members.InstanceMethods.InvokeVirtualVoidMethod(__id, this, null);
}

[Register("isClosed", "()Z", "")]
public unsafe bool IsClosed
{
get
{
const string __id = "isClosed.()Z";
var __rm = _members.InstanceMethods.InvokeVirtualBooleanMethod(__id, this, null);
return __rm;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using System;
using Android.Runtime;
using Java.Interop;

namespace Android.Gms.Games.Snapshot
{
// Binding for com.google.android.gms.games.snapshot.SnapshotMetadata
[Register("com/google/android/gms/games/snapshot/SnapshotMetadata", DoNotGenerateAcw = true)]
public sealed partial class SnapshotMetadata : Java.Lang.Object
{
static readonly JniPeerMembers _members =
new XAPeerMembers("com/google/android/gms/games/snapshot/SnapshotMetadata", typeof(SnapshotMetadata));

internal SnapshotMetadata(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { }

public override JniPeerMembers JniPeerMembers => _members;
protected override IntPtr ThresholdClass => _members.JniPeerType.PeerReference.Handle;
protected override Type ThresholdType => _members.ManagedPeerType;

// -------- SnapshotId --------
[Register("getSnapshotId", "()Ljava/lang/String;", "")]
public unsafe string SnapshotId
{
get
{
const string __id = "getSnapshotId.()Ljava/lang/String;";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod(__id, this, __args);
return JNIEnv.GetString(__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
}
}

// -------- Unique Name --------
[Register("getUniqueName", "()Ljava/lang/String;", "")]
public unsafe string UniqueName
{
get
{
const string __id = "getUniqueName.()Ljava/lang/String;";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod(__id, this, __args);
return JNIEnv.GetString(__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
}
}

// -------- Description --------
[Register ("getDescription", "()Ljava/lang/String;", "")]
public unsafe string Description
{
get
{
const string __id = "getDescription.()Ljava/lang/String;";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod(__id, this, __args);
return JNIEnv.GetString(__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
}
}

// -------- Last Modified Timestamp --------
[Register("getLastModifiedTimestamp", "()J", "")]
public unsafe long LastModifiedTimestamp
{
get
{
const string __id = "getLastModifiedTimestamp.()J";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualInt64Method(__id, this, __args);
return __rm;
}
}

// -------- Played Time --------
[Register("getPlayedTime", "()J", "")]
public unsafe long PlayedTime
{
get
{
const string __id = "getPlayedTime.()J";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualInt64Method(__id, this, __args);
return __rm;
}
}

// -------- Progress Value --------
[Register("getProgressValue", "()J", "")]
public unsafe long ProgressValue
{
get
{
const string __id = "getProgressValue.()J";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualInt64Method(__id, this, __args);
return __rm;
}
}

// -------- Device Name --------
[Register ("getDeviceName", "()Ljava/lang/String;", "")]
public unsafe string DeviceName
{
get
{
const string __id = "getDeviceName.()Ljava/lang/String;";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod(__id, this, __args);
return JNIEnv.GetString(__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
}
}

// -------- Cover Image URL --------
[Register("getCoverImageUrl", "()Ljava/lang/String;", "")]
public unsafe string CoverImageUrl
{
get
{
const string __id = "getCoverImageUrl.()Ljava/lang/String;";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod(__id, this, __args);
return JNIEnv.GetString(__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
}
}

// You can add more properties here, e.g., owner, playedTime, etc.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using Android.Runtime;
using Java.Interop;

namespace Android.Gms.Games
{
[Register("com/google/android/gms/games/SnapshotsClient$DataOrConflict", DoNotGenerateAcw = true)]
public sealed partial class DataOrConflict : Java.Lang.Object
{
static readonly JniPeerMembers _members =
new XAPeerMembers("com/google/android/gms/games/SnapshotsClient$DataOrConflict", typeof(DataOrConflict));

internal DataOrConflict(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { }

public override JniPeerMembers JniPeerMembers => _members;
protected override IntPtr ThresholdClass => _members.JniPeerType.PeerReference.Handle;
protected override Type ThresholdType => _members.ManagedPeerType;

// Raw getData() — Java signature is ()Ljava/lang/Object;
[Register("getData", "()Ljava/lang/Object;", "")]
public unsafe Java.Lang.Object GetDataRaw()
{
const string __id = "getData.()Ljava/lang/Object;";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod(__id, this, __args);
return Java.Lang.Object.GetObject<Java.Lang.Object>(__rm.Handle, JniHandleOwnership.TransferLocalRef);
}

// Typed convenience property that returns Snapshot or null
public Android.Gms.Games.Snapshot.Snapshot Data
{
get
{
var raw = GetDataRaw();
if (raw == null) return null;
return Java.Lang.Object.GetObject<Android.Gms.Games.Snapshot.Snapshot>(
raw.Handle,
JniHandleOwnership.DoNotTransfer);
}
}

// getConflict() returns SnapshotConflict
[Register("getConflict", "()Lcom/google/android/gms/games/SnapshotsClient$SnapshotConflict;", "")]
public unsafe SnapshotConflict GetConflict()
{
const string __id = "getConflict.()Lcom/google/android/gms/games/SnapshotsClient$SnapshotConflict;";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod(__id, this, __args);
return Java.Lang.Object.GetObject<SnapshotConflict>(__rm.Handle, JniHandleOwnership.TransferLocalRef);
}

// isConflict()
[Register("isConflict", "()Z", "")]
public unsafe bool IsConflict()
{
const string __id = "isConflict.()Z";
JniArgumentValue* __args = stackalloc JniArgumentValue[0];
var __rm = _members.InstanceMethods.InvokeVirtualBooleanMethod(__id, this, __args);
return __rm;
}
}
}
Loading