using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Android; using System.Runtime.InteropServices; using AOT; public class GPSTool { #if UNITY_IPHONE static Action callbackOut; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void ResultHandler(string resultString); [MonoPInvokeCallback(typeof(ResultHandler))] static void resultHandler(string parameter) { //Debug.Log("unity parameter:" + parameter); string[] components = parameter.Split(new char[] { '\t' }, 6); string address = components[5]; string[] addressOut = address.Split(new char[] { '\t' }, 3); callbackOut?.Invoke(addressOut); // 停止获取位置信息 LocationPluginInterface.StopUpdatingLocation(); } #endif #if UNITY_ANDROID private static Action callbackRecord; public static void OnLocationUpdate() { if (callbackRecord != null) { GetAddress(callbackRecord); callbackRecord = null; } } #endif //GPS获取地址 //成功返回:string[]{国,省,市} (数组中不允许有null) //失败返回:null public static void GetAddress(Action callback) { #if UNITY_ANDROID Action callAndroidMethod = delegate () { if (Application.isEditor) return; string[] address = null; using (var clsU3D = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (var objCtx = clsU3D.GetStatic("currentActivity")) using (var objGPSTool = new AndroidJavaClass("com.example.smartbowlib.GPSTool")) { bool gpsOpened = objGPSTool.CallStatic("hasOpenGPS", objCtx); if (!gpsOpened) { var view = OpenGPSView.Init(); if (view) view.onOpened = () => GetAddress(callback); return; } address = objGPSTool.CallStatic("getAddress", objCtx); if (address != null) { foreach (var item in address) { if (item == null) { address = null; break; } } } if (address != null) { Debug.Log("获取地理位置成功:" + string.Join(" ", address)); callback?.Invoke(address); } //如果安卓层未能获取到位置(比如gps刚打开),会等待gps更新,至到知道位置后,会通知Unity //因此可以先保留callback用于下次回调 else if (address == null) callbackRecord = callback; } }; List permissions = new List(); permissions.Add(Permission.CoarseLocation); permissions.Add(Permission.FineLocation); for (int i = permissions.Count - 1; i >= 0; i--) { if (Permission.HasUserAuthorizedPermission(permissions[i])) permissions.RemoveAt(i); } if (permissions.Count > 0) { var requestCB = new PermissionCallbacks(); int needPermissionCount = permissions.Count; requestCB.PermissionGranted += (s) => { Debug.Log("用户同意" + s); needPermissionCount--; if (needPermissionCount == 0) callAndroidMethod.Invoke(); }; bool hasExecuteOnDenied = false; requestCB.PermissionDenied += (s) => { Debug.Log("用户拒绝" + s); if (!hasExecuteOnDenied) { hasExecuteOnDenied = true; AlertNoPermission(); } }; requestCB.PermissionDeniedAndDontAskAgain += (s) => { Debug.Log("用户拒绝且要求不再询问" + s); if (!hasExecuteOnDenied) { hasExecuteOnDenied = true; AlertNoPermission(); } }; Permission.RequestUserPermissions(permissions.ToArray(), requestCB); } else { callAndroidMethod.Invoke(); } #endif #if UNITY_IPHONE callbackOut = callback; ResultHandler handler = new ResultHandler(resultHandler); IntPtr fp = Marshal.GetFunctionPointerForDelegate(handler); LocationPluginInterface.StartUpdatingLocation(fp); #endif } //提示用户:尚未授予定位权限 static void AlertNoPermission() { ModalManager.ShowConfirmModal_NoLocationPermission(); } }