123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- #if UNITY_ANDROID
- #pragma warning disable 0642 // Possible mistaken empty statement
- namespace GooglePlayGames.Android
- {
- using System;
- using System.Collections.Generic;
- using GooglePlayGames.BasicApi;
- using GooglePlayGames.BasicApi.Nearby;
- using GooglePlayGames.OurUtils;
- using UnityEngine;
- public class AndroidNearbyConnectionClient : INearbyConnectionClient
- {
- private volatile AndroidJavaObject mClient;
- private readonly static long NearbyClientId = 0L;
- private readonly static int ApplicationInfoFlags = 0x00000080;
- private readonly static string ServiceId = ReadServiceId();
- protected IMessageListener mAdvertisingMessageListener;
- public AndroidNearbyConnectionClient()
- {
- PlayGamesHelperObject.CreateObject();
- NearbyHelperObject.CreateObject(this);
- using (var nearbyClass = new AndroidJavaClass("com.google.android.gms.nearby.Nearby"))
- {
- mClient = nearbyClass.CallStatic<AndroidJavaObject>("getConnectionsClient",
- AndroidHelperFragment.GetActivity());
- }
- }
- public int MaxUnreliableMessagePayloadLength()
- {
- return NearbyConnectionConfiguration.MaxUnreliableMessagePayloadLength;
- }
- public int MaxReliableMessagePayloadLength()
- {
- return NearbyConnectionConfiguration.MaxReliableMessagePayloadLength;
- }
- public void SendReliable(List<string> recipientEndpointIds, byte[] payload)
- {
- InternalSend(recipientEndpointIds, payload);
- }
- public void SendUnreliable(List<string> recipientEndpointIds, byte[] payload)
- {
- InternalSend(recipientEndpointIds, payload);
- }
- private void InternalSend(List<string> recipientEndpointIds, byte[] payload)
- {
- Misc.CheckNotNull(recipientEndpointIds);
- Misc.CheckNotNull(payload);
- using (var payloadClass = new AndroidJavaClass("com.google.android.gms.nearby.connection.Payload"))
- using (var payloadObject = payloadClass.CallStatic<AndroidJavaObject>("fromBytes", payload))
- using (var task = mClient.Call<AndroidJavaObject>("sendPayload",
- AndroidJavaConverter.ToJavaStringList(recipientEndpointIds),
- payloadObject))
- ;
- }
- public void StartAdvertising(string name, List<string> appIdentifiers,
- TimeSpan? advertisingDuration, Action<AdvertisingResult> resultCallback,
- Action<ConnectionRequest> connectionRequestCallback)
- {
- Misc.CheckNotNull(resultCallback, "resultCallback");
- Misc.CheckNotNull(connectionRequestCallback, "connectionRequestCallback");
- if (advertisingDuration.HasValue && advertisingDuration.Value.Ticks < 0)
- {
- throw new InvalidOperationException("advertisingDuration must be positive");
- }
- connectionRequestCallback = ToOnGameThread(connectionRequestCallback);
- resultCallback = ToOnGameThread(resultCallback);
- AdvertisingConnectionLifecycleCallbackProxy callbackProxy =
- new AdvertisingConnectionLifecycleCallbackProxy(resultCallback, connectionRequestCallback, this);
- using (var connectionLifecycleCallback =
- new AndroidJavaObject("com.google.games.bridge.ConnectionLifecycleCallbackProxy", callbackProxy))
- using (var advertisingOptions = CreateAdvertisingOptions())
- using (var task = mClient.Call<AndroidJavaObject>("startAdvertising", name, GetServiceId(),
- connectionLifecycleCallback, advertisingOptions))
- {
- AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
- task,
- v => NearbyHelperObject.StartAdvertisingTimer(advertisingDuration)
- );
- }
- }
- private AndroidJavaObject CreateAdvertisingOptions()
- {
- using (var strategy = new AndroidJavaClass("com.google.android.gms.nearby.connection.Strategy")
- .GetStatic<AndroidJavaObject>("P2P_CLUSTER"))
- using (var builder =
- new AndroidJavaObject("com.google.android.gms.nearby.connection.AdvertisingOptions$Builder"))
- using (builder.Call<AndroidJavaObject>("setStrategy", strategy))
- {
- return builder.Call<AndroidJavaObject>("build");
- }
- }
- private class AdvertisingConnectionLifecycleCallbackProxy : AndroidJavaProxy
- {
- private Action<AdvertisingResult> mResultCallback;
- private Action<ConnectionRequest> mConnectionRequestCallback;
- private AndroidNearbyConnectionClient mClient;
- private string mLocalEndpointName;
- public AdvertisingConnectionLifecycleCallbackProxy(Action<AdvertisingResult> resultCallback,
- Action<ConnectionRequest> connectionRequestCallback, AndroidNearbyConnectionClient client) : base(
- "com/google/games/bridge/ConnectionLifecycleCallbackProxy$Callback")
- {
- mResultCallback = resultCallback;
- mConnectionRequestCallback = connectionRequestCallback;
- mClient = client;
- }
- public void onConnectionInitiated(string endpointId, AndroidJavaObject connectionInfo)
- {
- mLocalEndpointName = connectionInfo.Call<string>("getEndpointName");
- mConnectionRequestCallback(new ConnectionRequest(endpointId, mLocalEndpointName, mClient.GetServiceId(),
- new byte[0]));
- }
- public void onConnectionResult(string endpointId, AndroidJavaObject connectionResolution)
- {
- int statusCode;
- using (var status = connectionResolution.Call<AndroidJavaObject>("getStatus"))
- {
- statusCode = status.Call<int>("getStatusCode");
- }
- if (statusCode == 0) // STATUS_OK
- {
- mResultCallback(new AdvertisingResult(ResponseStatus.Success, mLocalEndpointName));
- return;
- }
- if (statusCode == 8001) // STATUS_ALREADY_ADVERTISING
- {
- mResultCallback(new AdvertisingResult(ResponseStatus.NotAuthorized, mLocalEndpointName));
- return;
- }
- mResultCallback(new AdvertisingResult(ResponseStatus.InternalError, mLocalEndpointName));
- }
- public void onDisconnected(string endpointId)
- {
- if (mClient.mAdvertisingMessageListener != null)
- {
- mClient.mAdvertisingMessageListener.OnRemoteEndpointDisconnected(endpointId);
- }
- }
- }
- public void StopAdvertising()
- {
- mClient.Call("stopAdvertising");
- mAdvertisingMessageListener = null;
- }
- public void SendConnectionRequest(string name, string remoteEndpointId, byte[] payload,
- Action<ConnectionResponse> responseCallback, IMessageListener listener)
- {
- Misc.CheckNotNull(listener, "listener");
- var listenerOnGameThread = new OnGameThreadMessageListener(listener);
- DiscoveringConnectionLifecycleCallback cb =
- new DiscoveringConnectionLifecycleCallback(responseCallback, listenerOnGameThread, mClient);
- using (var connectionLifecycleCallback =
- new AndroidJavaObject("com.google.games.bridge.ConnectionLifecycleCallbackProxy", cb))
- using (mClient.Call<AndroidJavaObject>("requestConnection", name, remoteEndpointId,
- connectionLifecycleCallback))
- ;
- }
- public void AcceptConnectionRequest(string remoteEndpointId, byte[] payload, IMessageListener listener)
- {
- Misc.CheckNotNull(listener, "listener");
- mAdvertisingMessageListener = new OnGameThreadMessageListener(listener);
- using (var payloadCallback = new AndroidJavaObject("com.google.games.bridge.PayloadCallbackProxy",
- new PayloadCallback(listener)))
- using (mClient.Call<AndroidJavaObject>("acceptConnection", remoteEndpointId, payloadCallback))
- ;
- }
- private class PayloadCallback : AndroidJavaProxy
- {
- private IMessageListener mListener;
- public PayloadCallback(IMessageListener listener) : base(
- "com/google/games/bridge/PayloadCallbackProxy$Callback")
- {
- mListener = listener;
- }
- public void onPayloadReceived(String endpointId, AndroidJavaObject payload)
- {
- if (payload.Call<int>("getType") != 1) // 1 for BYTES
- {
- return;
- }
- mListener.OnMessageReceived(endpointId, payload.Call<byte[]>("asBytes"), /* isReliableMessage */ true);
- }
- }
- public void StartDiscovery(string serviceId, TimeSpan? advertisingDuration,
- IDiscoveryListener listener)
- {
- Misc.CheckNotNull(serviceId, "serviceId");
- Misc.CheckNotNull(listener, "listener");
- var listenerOnGameThread = new OnGameThreadDiscoveryListener(listener);
- if (advertisingDuration.HasValue && advertisingDuration.Value.Ticks < 0)
- {
- throw new InvalidOperationException("advertisingDuration must be positive");
- }
- using (var endpointDiscoveryCallback = new AndroidJavaObject(
- "com.google.games.bridge.EndpointDiscoveryCallbackProxy",
- new EndpointDiscoveryCallback(listenerOnGameThread)))
- using (var discoveryOptions = CreateDiscoveryOptions())
- using (var task = mClient.Call<AndroidJavaObject>("startDiscovery", serviceId, endpointDiscoveryCallback,
- discoveryOptions))
- {
- AndroidTaskUtils.AddOnSuccessListener<AndroidJavaObject>(
- task,
- v => NearbyHelperObject.StartDiscoveryTimer(advertisingDuration)
- );
- }
- }
- private class DiscoveringConnectionLifecycleCallback : AndroidJavaProxy
- {
- private Action<ConnectionResponse> mResponseCallback;
- private IMessageListener mListener;
- private AndroidJavaObject mClient;
- public DiscoveringConnectionLifecycleCallback(Action<ConnectionResponse> responseCallback,
- IMessageListener listener, AndroidJavaObject client) : base(
- "com/google/games/bridge/ConnectionLifecycleCallbackProxy$Callback")
- {
- mResponseCallback = responseCallback;
- mListener = listener;
- mClient = client;
- }
- public void onConnectionInitiated(string endpointId, AndroidJavaObject connectionInfo)
- {
- using (var payloadCallback = new AndroidJavaObject("com.google.games.bridge.PayloadCallbackProxy",
- new PayloadCallback(mListener)))
- using (mClient.Call<AndroidJavaObject>("acceptConnection", endpointId, payloadCallback))
- ;
- }
- public void onConnectionResult(string endpointId, AndroidJavaObject connectionResolution)
- {
- int statusCode;
- using (var status = connectionResolution.Call<AndroidJavaObject>("getStatus"))
- {
- statusCode = status.Call<int>("getStatusCode");
- }
- if (statusCode == 0) // STATUS_OK
- {
- mResponseCallback(ConnectionResponse.Accepted(NearbyClientId, endpointId, new byte[0]));
- return;
- }
- if (statusCode == 8002) // STATUS_ALREADY_DISCOVERING
- {
- mResponseCallback(ConnectionResponse.AlreadyConnected(NearbyClientId, endpointId));
- return;
- }
- mResponseCallback(ConnectionResponse.Rejected(NearbyClientId, endpointId));
- }
- public void onDisconnected(string endpointId)
- {
- mListener.OnRemoteEndpointDisconnected(endpointId);
- }
- }
- private AndroidJavaObject CreateDiscoveryOptions()
- {
- using (var strategy =
- new AndroidJavaClass("com.google.android.gms.nearby.connection.Strategy").GetStatic<AndroidJavaObject>(
- "P2P_CLUSTER"))
- using (var builder =
- new AndroidJavaObject("com.google.android.gms.nearby.connection.DiscoveryOptions$Builder"))
- using (builder.Call<AndroidJavaObject>("setStrategy", strategy))
- {
- return builder.Call<AndroidJavaObject>("build");
- }
- }
- private class EndpointDiscoveryCallback : AndroidJavaProxy
- {
- private IDiscoveryListener mListener;
- public EndpointDiscoveryCallback(IDiscoveryListener listener) : base(
- "com/google/games/bridge/EndpointDiscoveryCallbackProxy$Callback")
- {
- mListener = listener;
- }
- public void onEndpointFound(string endpointId, AndroidJavaObject endpointInfo)
- {
- mListener.OnEndpointFound(CreateEndPointDetails(endpointId, endpointInfo));
- }
- public void onEndpointLost(string endpointId)
- {
- mListener.OnEndpointLost(endpointId);
- }
- private EndpointDetails CreateEndPointDetails(string endpointId, AndroidJavaObject endpointInfo)
- {
- return new EndpointDetails(
- endpointId,
- endpointInfo.Call<string>("getEndpointName"),
- endpointInfo.Call<string>("getServiceId")
- );
- }
- }
- private class OnGameThreadMessageListener : IMessageListener
- {
- private readonly IMessageListener mListener;
- public OnGameThreadMessageListener(IMessageListener listener)
- {
- mListener = Misc.CheckNotNull(listener);
- }
- public void OnMessageReceived(string remoteEndpointId, byte[] data,
- bool isReliableMessage)
- {
- PlayGamesHelperObject.RunOnGameThread(() => mListener.OnMessageReceived(
- remoteEndpointId, data, isReliableMessage));
- }
- public void OnRemoteEndpointDisconnected(string remoteEndpointId)
- {
- PlayGamesHelperObject.RunOnGameThread(
- () => mListener.OnRemoteEndpointDisconnected(remoteEndpointId));
- }
- }
- private class OnGameThreadDiscoveryListener : IDiscoveryListener
- {
- private readonly IDiscoveryListener mListener;
- public OnGameThreadDiscoveryListener(IDiscoveryListener listener)
- {
- mListener = listener;
- }
- public void OnEndpointFound(EndpointDetails discoveredEndpoint)
- {
- PlayGamesHelperObject.RunOnGameThread(() => mListener.OnEndpointFound(discoveredEndpoint));
- }
- public void OnEndpointLost(string lostEndpointId)
- {
- PlayGamesHelperObject.RunOnGameThread(() => mListener.OnEndpointLost(lostEndpointId));
- }
- }
- public void StopDiscovery(string serviceId)
- {
- mClient.Call("stopDiscovery");
- }
- public void RejectConnectionRequest(string requestingEndpointId)
- {
- Misc.CheckNotNull(requestingEndpointId, "requestingEndpointId");
- using (var task = mClient.Call<AndroidJavaObject>("rejectConnection", requestingEndpointId)) ;
- }
- public void DisconnectFromEndpoint(string remoteEndpointId)
- {
- mClient.Call("disconnectFromEndpoint", remoteEndpointId);
- }
- public void StopAllConnections()
- {
- mClient.Call("stopAllEndpoints");
- mAdvertisingMessageListener = null;
- }
- public string GetAppBundleId()
- {
- using (var activity = AndroidHelperFragment.GetActivity())
- {
- return activity.Call<string>("getPackageName");
- }
- }
- public string GetServiceId()
- {
- return ServiceId;
- }
- private static string ReadServiceId()
- {
- using (var activity = AndroidHelperFragment.GetActivity())
- {
- string packageName = activity.Call<string>("getPackageName");
- using (var pm = activity.Call<AndroidJavaObject>("getPackageManager"))
- using (var appInfo =
- pm.Call<AndroidJavaObject>("getApplicationInfo", packageName, ApplicationInfoFlags))
- using (var bundle = appInfo.Get<AndroidJavaObject>("metaData"))
- {
- string sysId = bundle.Call<string>("getString",
- "com.google.android.gms.nearby.connection.SERVICE_ID");
- OurUtils.Logger.d("SystemId from Manifest: " + sysId);
- return sysId;
- }
- }
- }
- private static Action<T> ToOnGameThread<T>(Action<T> toConvert)
- {
- return (val) => PlayGamesHelperObject.RunOnGameThread(() => toConvert(val));
- }
- private static Action<T1, T2> ToOnGameThread<T1, T2>(Action<T1, T2> toConvert)
- {
- return (val1, val2) => PlayGamesHelperObject.RunOnGameThread(() => toConvert(val1, val2));
- }
- }
- }
- #endif
|