using System; using UnityEngine; namespace Cryville.Common.Unity.Input { public class AndroidTouchHandler : InputHandler { readonly AndroidTouchListener _listener; readonly AndroidJavaClass _systemClock; public AndroidTouchHandler() { if (Environment.OSVersion.Platform != PlatformID.Unix) throw new NotSupportedException("Android touch is not supported on this device"); _systemClock = new AndroidJavaClass("android.os.SystemClock"); new AndroidJavaClass("com.unity3d.player.UnityPlayer") .GetStatic("currentActivity") .Get("mUnityPlayer") .Call("setOnTouchListener", _listener = new AndroidTouchListener(this)); } protected override void Activate() { _listener.Activated = true; } protected override void Deactivate() { _listener.Activated = false; } public override void Dispose(bool disposing) { if (disposing) { Deactivate(); } } public override bool IsNullable(int type) { if (type != 0) throw new ArgumentOutOfRangeException("type"); return true; } public override byte GetDimension(int type) { if (type != 0) throw new ArgumentOutOfRangeException("type"); return 2; } public override string GetTypeName(int type) { switch (type) { case 0: return "Android Touch"; default: throw new ArgumentOutOfRangeException("type"); } } public override double GetCurrentTimestamp() { return _systemClock.CallStatic("uptimeMillis") / 1000.0; } class AndroidTouchListener : AndroidJavaProxy { public bool Activated { get; set; } readonly AndroidTouchHandler _handler; public AndroidTouchListener(AndroidTouchHandler handler) : base("android.view.View$OnTouchListener") { _handler = handler; } #pragma warning disable IDE1006 #pragma warning disable IDE0060 public bool onTouch(AndroidJavaObject v, AndroidJavaObject e) { if (!Activated) return false; try { int pointerCount = e.Call("getPointerCount"); for (int i = 0; i < pointerCount; i++) { int id = e.Call("getPointerId", i); double time = e.Call("getEventTime") / 1000.0; int action = e.Call("getActionMasked"); Vector2 pos = UnityCameraUtils.ScreenToWorldPoint(new Vector2( e.Call("getX", i), e.Call("getY", i) )); _handler.Feed(0, id, new InputVector(time, pos)); if (action == 1 /*ACTION_UP*/ || action == 3 /*ACTION_CANCEL*/ || (action == 6 /*ACTION_POINTER_UP*/ && e.Call("getActionIndex") == i)) { _handler.Feed(0, id, new InputVector(time)); } } } catch (Exception ex) { Logger.Log("main", 4, "Input", "An error occured while handling an Android touch event: {0}", ex); } return false; } #pragma warning restore IDE0060 #pragma warning restore IDE1006 } } }