diff --git a/app/src/main/java/com/nsgk/ruralWeb/location/NSLocationInfo.java b/app/src/main/java/com/nsgk/ruralWeb/location/NSLocationInfo.java new file mode 100644 index 0000000..6d7266a --- /dev/null +++ b/app/src/main/java/com/nsgk/ruralWeb/location/NSLocationInfo.java @@ -0,0 +1,25 @@ +package com.nsgk.ruralWeb.location; + +public final class NSLocationInfo +{ + public final String provider; + public final double longitude; + public final double latitude; + + public NSLocationInfo(String provider, double longitude, double latitude) + { + this.provider = provider; + this.longitude = longitude; + this.latitude = latitude; + } + + @Override + public String toString() + { + return "定位信息: " + + "提供器=" + provider + + "; 经度=" + longitude + + "; 纬度=" + latitude + ; + } +} diff --git a/app/src/main/java/com/nsgk/ruralWeb/location/NSRealtimeLocation.java b/app/src/main/java/com/nsgk/ruralWeb/location/NSRealtimeLocation.java new file mode 100644 index 0000000..390a677 --- /dev/null +++ b/app/src/main/java/com/nsgk/ruralWeb/location/NSRealtimeLocation.java @@ -0,0 +1,369 @@ +package com.nsgk.ruralWeb.location; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.HandlerThread; +import android.os.Looper; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.amap.api.location.AMapLocation; +import com.amap.api.location.AMapLocationClient; +import com.amap.api.location.AMapLocationClientOption; +import com.amap.api.location.AMapLocationListener; +import com.amap.api.location.CoordinateConverter; +import com.amap.api.location.DPoint; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +// 主线程调用, 无线程安全 +public class NSRealtimeLocation implements LocationListener +{ + // 定位提供器 + public static final int FLAG_PROVIDER_NETWORK = 1; // 网络定位 + public static final int FLAG_PROVIDER_GPS = 1 << 1; // GPS定位 + + // 定位提供器优先级 + public static final int FLAG_PRIORITY_NETWORK = 1 << 2; // 网络定位优先 + public static final int FLAG_PRIORITY_GPS = 1 << 3; // GPS定位优先 + + // 线程 + public static final int FLAG_BUILTIN_THREAD = 1 << 4; // 使用内建线程 + public static final int FLAG_CUSTOM_THREAD = 1 << 5; // 使用外部线程 + public static final int FLAG_MAIN_THREAD = 1 << 6; // 使用主线程 + + public static final int DEFAULT_FLAG = FLAG_PROVIDER_NETWORK | FLAG_PROVIDER_GPS | FLAG_PRIORITY_NETWORK; + + + public static final int OPTION_MIN_TIME = 1; // 最小定位间隔(毫秒) 默认60000 + public static final int OPTION_MIN_DISTANCE = 2; // 最小定位距离变化(米) 默认10 + + private static final int DEFAULT_MIN_TIME = 1000; + private static final int DEFAULT_MIN_DISTANCE = 1; + + private static final String ID_TAG = NSRealtimeLocation.class.getName(); + + private final Object m_lock = new Object(); + + private LocationManager m_locationManager; + private final Context m_context; + private int m_flag = DEFAULT_FLAG; + private NSLocationInfo m_lastLocation = null; + private HandlerThread m_thread = null; + private Looper m_customLooper = null; + private AtomicInteger m_readOnce = new AtomicInteger(-1); + private Map m_options = new HashMap<>(); + private String m_provider = null; + private Looper m_looper = null; + + public NSRealtimeLocation(Context context) + { + m_context = context; + } + + public boolean Init(int flag) + { + if(IsInitialized()) + { + Log.e(ID_TAG, "定位已初始化"); + return true; + } + + if(!HasFlag(FLAG_PROVIDER_NETWORK | FLAG_PROVIDER_GPS)) + { + Log.e(ID_TAG, "请设置定位提供器"); + return false; + } + + try + { + m_readOnce.set(-1); + m_flag = flag < 0 ? DEFAULT_FLAG : flag; + + m_locationManager = (LocationManager) m_context.getSystemService(Context.LOCATION_SERVICE); + + //初始化定位 + if(HasFlag(FLAG_BUILTIN_THREAD)) + { + m_thread = new HandlerThread("系统实时内建定位"); + m_thread.start(); + m_looper = m_thread.getLooper(); + Log.d(ID_TAG, "定位使用内建线程: " + m_thread.getId()); + } + else if(HasFlag(FLAG_CUSTOM_THREAD)) + { + if(null == m_customLooper) + { + throw new RuntimeException("请先传入线程Looper"); + } + m_looper = m_customLooper; + Log.d(ID_TAG, "定位使用用户指定线程: " + m_customLooper.getThread().getId()); + } + else if(HasFlag(FLAG_MAIN_THREAD)) + { + Looper mainLooper = Looper.getMainLooper(); + m_looper = mainLooper; + Log.d(ID_TAG, "定位使用主线程: " + mainLooper.getThread().getId()); + } + else + { + m_looper = Looper.myLooper(); + Log.d(ID_TAG, "定位使用当前线程: " + Thread.currentThread().getId()); + } + + Log.i(ID_TAG, "定位初始化完成"); + return true; + } + catch(Exception e) + { + e.printStackTrace(); + m_locationManager = null; + return false; + } + } + + public void SetThread(Looper looper) + { + CheckInitialization(false); + m_customLooper = looper; + } + + public void SetThread(HandlerThread thread) + { + CheckInitialization(false); + m_customLooper = thread.getLooper(); + } + + public boolean IsRunning() + { + return IsInitialized() && null != m_provider; + } + + public void Start() + { + Run(-1); + } + + public void Stop() + { + CheckInitialization(true); + + m_locationManager.removeUpdates(this); + m_provider = null; + + Log.i(ID_TAG, "定位停止"); + } + + public void Shutdown() + { + if(!IsInitialized()) + { + Log.e(ID_TAG, "请先初始化"); + return; + } + + Stop(); + + m_locationManager = null; + if(null != m_thread) + { + m_thread.quit(); + m_thread = null; + Log.d(ID_TAG, "内建线程结束"); + } + + Log.i(ID_TAG, "定位销毁"); + } + + public boolean IsInitialized() + { + return null != m_locationManager; + } + + private void CheckInitialization(boolean inited) + { + if(IsInitialized() != inited) + { + String msg = inited ? "定位未初始化" : "定位已初始化"; + Log.e(ID_TAG, msg); + throw new RuntimeException(msg); + } + } + + private boolean HasFlag(int f) + { + return (m_flag & f) != 0; + } + + public void SetOption(int type, Object value) + { + //CheckInitialization(false); + m_options.put(type, value); + } + + @SuppressLint("unchecked") + private T GetOption(int type, T def) + { + Object o = m_options.get(type); + if(null == o) + return def; + return (T) o; + } + + private void InitOptions() + { + List providers = new ArrayList<>(); + m_provider = null; + if(HasFlag(FLAG_PROVIDER_NETWORK)) + { + if(m_locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) + providers.add(LocationManager.NETWORK_PROVIDER); + else + Log.w(ID_TAG, "网络定位提供器未启用"); + } + if(HasFlag(FLAG_PROVIDER_GPS)) + { + if(m_locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) + providers.add(LocationManager.GPS_PROVIDER); + else + Log.w(ID_TAG, "GPS定位提供器未启用"); + } + if(providers.isEmpty()) + throw new RuntimeException("无定位提供器"); + + if(HasFlag(FLAG_PRIORITY_NETWORK)) + { + if(providers.contains(LocationManager.NETWORK_PROVIDER)) + m_provider = LocationManager.NETWORK_PROVIDER; + else + m_provider = LocationManager.GPS_PROVIDER; + } + else if(HasFlag(FLAG_PRIORITY_GPS)) + { + if(providers.contains(LocationManager.GPS_PROVIDER)) + m_provider = LocationManager.GPS_PROVIDER; + else + m_provider = LocationManager.NETWORK_PROVIDER; + } +/* else + { + if(providers.contains(LocationManager.NETWORK_PROVIDER)) + m_provider = LocationManager.NETWORK_PROVIDER; + else + m_provider = LocationManager.GPS_PROVIDER; + }*/ + + if(null == m_provider) + throw new RuntimeException("未确定定位提供器"); + + Log.i(ID_TAG, "使用定位器: " + m_provider); + } + + @SuppressLint("MissingPermission") + private void Run(int num) + { + CheckInitialization(true); + + Stop(); + + m_readOnce.set(num); + + InitOptions(); + + int minTime = GetOption(OPTION_MIN_TIME, DEFAULT_MIN_TIME); + int minDistance = GetOption(OPTION_MIN_DISTANCE, DEFAULT_MIN_DISTANCE); + m_locationManager.requestLocationUpdates(m_provider, minTime, minDistance, this, m_looper); + + Location lastKnownLocation = m_locationManager.getLastKnownLocation(m_provider); + SetLastLocation(lastKnownLocation); + + Log.i(ID_TAG, "定位开始"); + } + + private void SetLastLocation(Location location) + { + if(null != location) + { + m_lastLocation = new NSLocationInfo(location.getProvider(), location.getLongitude(), location.getLatitude()); + } + else + { + m_lastLocation = null; + } + } + + /** + * 同步调用, 会锁住线程 + */ + public NSLocationInfo Read(int count) + { + CheckInitialization(true); +/* if(IsRunning()) + { + throw new RuntimeException("请先停止定位"); + }*/ + + Log.d(ID_TAG, "定位线程: " + Thread.currentThread().getId()); + synchronized(m_lock) + { + try + { + CleanLastLocation(); + Run(count); + m_lock.wait(); + } + catch(Exception e) + { + throw new RuntimeException(e); + } + finally + { + Stop(); + } + } + return m_lastLocation; + } + + public NSLocationInfo GetLastLocation() + { + return m_lastLocation; + } + + public void CleanLastLocation() + { + m_lastLocation = null; + } + + /* + 在调用线程中执行 + */ + @Override + public void onLocationChanged(@NonNull Location location) + { + Log.d(ID_TAG, "onLocationChanged线程: " + Thread.currentThread().getId()); + System.err.println(location); + SetLastLocation(location); + //if(null != location) + { + if(m_readOnce.get() > 0) + { + m_readOnce.decrementAndGet(); + if(m_readOnce.get() == 0) + { + synchronized(m_lock) + { + m_lock.notifyAll(); + } + } + } + } + } +} diff --git a/app/src/main/java/com/nsgk/ruralWeb/location/NSSystemLocation.java b/app/src/main/java/com/nsgk/ruralWeb/location/NSSystemLocation.java new file mode 100644 index 0000000..81f9f1c --- /dev/null +++ b/app/src/main/java/com/nsgk/ruralWeb/location/NSSystemLocation.java @@ -0,0 +1,189 @@ +package com.nsgk.ruralWeb.location; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.location.Criteria; +import android.location.Location; +import android.location.LocationManager; +import android.os.Build; +import android.util.Log; +import android.widget.Toast; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +public class NSSystemLocation +{ + private static final String ID_TAG = NSSystemLocation.class.getName(); + public static final String FUSED_PROVIDER = "fused"; + + private final Context m_context; + private NSLocationInfo m_lastLocation = null; + + public NSSystemLocation(Context context) + { + m_context = context; + } + + public NSLocationInfo GetLocation(String provider) + { + NSLocationInfo loc; + + try + { + loc = GetHighLocation(provider); + if(null == loc) + loc = GetLastLocation(provider); + + if(null != loc) + m_lastLocation = loc; + else + ShowToast("定位失败, 请先开启位置服务", Toast.LENGTH_LONG); + + return loc; + } + catch(Throwable e) + { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + @SuppressLint("MissingPermission") + private NSLocationInfo GetLastLocation(final String type) + { + NSLocationInfo loc = null; + try + { + LocationManager lm = (LocationManager) m_context.getSystemService(Context.LOCATION_SERVICE); + + List allProviders = lm.getAllProviders(); + Log.i(ID_TAG, "使用最近所有定位提供器: " + allProviders); + Map map = new HashMap<>(); + for(String provider : allProviders) + { + Location lastKnownLocation = lm.getLastKnownLocation(provider); + if(null == lastKnownLocation) + continue; + NSLocationInfo l = new NSLocationInfo(provider, lastKnownLocation.getLongitude(), lastKnownLocation.getLatitude()); + map.put(provider, l); + } + + Log.i(ID_TAG, "最近定位提供器结果: " + map); + if(null != type && !type.isEmpty() && map.containsKey(type)) + loc = map.get(type); + else if(map.containsKey(LocationManager.GPS_PROVIDER)) + loc = map.get(LocationManager.GPS_PROVIDER); + else if(map.containsKey(LocationManager.NETWORK_PROVIDER)) + loc = map.get(LocationManager.NETWORK_PROVIDER); + else if(map.containsKey(FUSED_PROVIDER)) + loc = map.get(FUSED_PROVIDER); + else if(map.containsKey(LocationManager.PASSIVE_PROVIDER)) + loc = map.get(LocationManager.PASSIVE_PROVIDER); + if(null == loc) + Log.i(ID_TAG, "所有提供器无最近定位"); + else + Log.i(ID_TAG, "使用提供器最近定位: " + loc.provider); + } + catch(Throwable e) + { + e.printStackTrace(); + } + return loc; + } + + @SuppressLint("MissingPermission") + private NSLocationInfo GetHighLocation(String provider) + { + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + { + return null; + } + + NSLocationInfo loc = null; + try + { + LocationManager lm = (LocationManager) m_context.getSystemService(Context.LOCATION_SERVICE); + if(null != provider) + { + if(LocationManager.GPS_PROVIDER.equals(provider)) + { + if(!lm.isProviderEnabled(provider)) + { + Log.w(ID_TAG, "GPS定位提供器未启用, 尝试网络定位器"); + provider = LocationManager.NETWORK_PROVIDER; + if(!lm.isProviderEnabled(provider)) + { + Log.w(ID_TAG, "网络定位提供器也未启用"); + provider = null; + } + } + } + else if(LocationManager.NETWORK_PROVIDER.equals(provider)) + { + Log.w(ID_TAG, "网络定位提供器未启用, 尝试GPS定位器"); + if(!lm.isProviderEnabled(provider)) + { + provider = LocationManager.GPS_PROVIDER; + if(!lm.isProviderEnabled(provider)) + { + Log.w(ID_TAG, "GPS定位提供器也未启用"); + provider = null; + } + } + } + } + + if(null == provider) + { + Criteria criteria = new Criteria(); + criteria.setAccuracy(Criteria.ACCURACY_FINE); // 高精度 +// criteria.setPowerRequirement(Criteria.POWER_HIGH); +// criteria.setAltitudeRequired(false); + provider = lm.getBestProvider(criteria, true); + } + Log.i(ID_TAG, "使用高精度定位提供器: " + provider); + + if(null == provider) + { + Log.i(ID_TAG, "无法获取高精度定位提供器"); + return null; + } + + CompletableFuture future = new CompletableFuture<>(); + lm.getCurrentLocation(provider, null, m_context.getMainExecutor(), future::complete); + Location location = future.get(); + if(null == location) + { + Log.i(ID_TAG, "无法使用高精度提供器定位"); + return null; + } + loc = new NSLocationInfo(provider, location.getLongitude(), location.getLatitude()); + Log.i(ID_TAG, "使用高精度提供器获取定位: " + loc); + } + catch(Throwable e) + { + e.printStackTrace(); + } + return loc; + } + + private void ShowToast(final String message, int duration) + { + ((Activity)m_context).runOnUiThread((new Runnable() { + @Override + public void run() + { + Toast.makeText(m_context, message, duration).show(); + } + })); + } + + public NSLocationInfo GetLastLocation() + { + return m_lastLocation; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nsgk/ruralWeb/web/NSEnvWindowObject.java b/app/src/main/java/com/nsgk/ruralWeb/web/NSEnvWindowObject.java new file mode 100644 index 0000000..d1ab633 --- /dev/null +++ b/app/src/main/java/com/nsgk/ruralWeb/web/NSEnvWindowObject.java @@ -0,0 +1,288 @@ +package com.nsgk.ruralWeb.web; + +import android.app.Activity; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.location.LocationManager; +import android.os.Handler; +import android.util.Log; +import android.webkit.JavascriptInterface; +import android.webkit.ValueCallback; +import android.webkit.WebView; +import android.widget.Toast; + +import androidx.core.app.ActivityCompat; + +import com.nsgk.ruralWeb.FullscreenActivity; +import com.nsgk.ruralWeb.enums.NSEnums; +import com.nsgk.ruralWeb.location.NSLocationInfo; +import com.nsgk.ruralWeb.location.NSAMapLocation; +import com.nsgk.ruralWeb.location.NSRealtimeLocation; +import com.nsgk.ruralWeb.location.NSSystemLocation; +import com.nsgk.ruralWeb.sys.NSConstants; +import com.nsgk.ruralWeb.sys.NSPreference; +import com.nsgk.ruralWeb.utils.NSContextUtils; + +public class NSEnvWindowObject +{ + private static final String ID_TAG = NSEnvWindowObject.class.getName(); + private static final String FUSED_PROVIDER = "fused"; + + private final Handler m_handler; + private final Context m_context; + private final WebView m_webView; + + private final NSSystemLocation location; + + private final NSAMapLocation amapLocation; + private final NSRealtimeLocation realtimeLocation; + private final NSPreference preference; + // 最近一次获取到的定位坐标, 如果获取定位失败则返回此值. 可能不需要, 因为PASSIVE_PROVIDER就为最近的定位 + private String lastLocation = null; + + public NSEnvWindowObject(Context context, Handler handler, WebView webView) + { + m_context = context; + m_handler = handler; + m_webView = webView; + location = new NSSystemLocation(m_context); + amapLocation = new NSAMapLocation(m_context); + realtimeLocation = new NSRealtimeLocation(m_context); + preference = new NSPreference(m_context); + } + + public void OnDestroy() + { + if(amapLocation.IsInitialized()) + amapLocation.Shutdown(); + if(realtimeLocation.IsInitialized()) + realtimeLocation.Shutdown(); + } + + @JavascriptInterface + public void Toast(final String message) + { + ShowToast(message, Toast.LENGTH_LONG); + } + + private void ShowToast(final String message, int duration) + { + RunOnUIThread(new Runnable() { + @Override + public void run() + { + Toast.makeText(m_context, message, duration).show(); + } + }); + } + + @JavascriptInterface + public void Log(final String message) + { + Log.i(ID_TAG, message); + } + + @JavascriptInterface + public String GetLocation(final String type) + { + Log.d(ID_TAG, "Web线程: " + Thread.currentThread().getId()); + + if(!CheckLocationPermission()) + { + return lastLocation; + } + + NSLocationInfo loc; + String location = preference.GetString(NSPreference.LOCATION_SCHEME, NSConstants.DEFAULT_LOCATION_SCHEME); + String provider = preference.GetString(NSPreference.LOCATION_PROVIDER, NSConstants.DEFAULT_LOCATION_PROVIDER); + Log.d(ID_TAG, "定位提供器: " + provider); + switch(location) + { + case NSEnums.LocationScheme.GAODE: + loc = GetAMapLocation(); + if(null == loc) + loc = GetBuiltInLocation(provider); + break; + case NSEnums.LocationScheme.REALTIME: + loc = GetRealtimeLocation(); + if(null == loc) + loc = GetBuiltInLocation(provider); + break; + case NSEnums.LocationScheme.SYSTEM: + default: + loc = GetBuiltInLocation(provider); + break; + } + + return SetLastLocation(loc); + } + + private String ReturnLocation(NSLocationInfo loc) + { + return loc.longitude + "," + loc.latitude; + } + + private String SetLastLocation(NSLocationInfo loc) + { + if(null != loc) + lastLocation = ReturnLocation(loc); + return lastLocation; + } + + private NSLocationInfo GetBuiltInLocation(String type) + { + Log.i(ID_TAG, "使用系统定位"); + NSLocationInfo loc = null; + try + { + long start = System.currentTimeMillis(); + loc = location.GetLocation(type); + long end = System.currentTimeMillis(); + Log.i(ID_TAG, "系统定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); + } + catch(Throwable e) + { + e.printStackTrace(); + } + return loc; + } + + private NSLocationInfo GetRealtimeLocation() + { + Log.i(ID_TAG, "使用系统实时定位"); + NSLocationInfo loc = null; + try + { + NSPreference preference = new NSPreference(m_context); + if(!realtimeLocation.IsInitialized()) + { + realtimeLocation.SetOption(NSRealtimeLocation.OPTION_MIN_TIME, preference.GetIntFromString(NSPreference.LOCATION_REALTIME_INTERVAL, NSConstants.DEFAULT_LOCATION_REALTIME_INTERVAL)); + realtimeLocation.SetOption(NSRealtimeLocation.OPTION_MIN_DISTANCE, preference.GetIntFromString(NSPreference.LOCATION_REALTIME_DISTANCE, NSConstants.DEFAULT_LOCATION_REALTIME_DISTANCE)); + int flag = NSRealtimeLocation.DEFAULT_FLAG | NSRealtimeLocation.FLAG_BUILTIN_THREAD; + String provider = preference.GetString(NSPreference.LOCATION_PROVIDER, NSConstants.DEFAULT_LOCATION_PROVIDER); + if(LocationManager.GPS_PROVIDER.equals(provider)) + { + flag &= ~NSRealtimeLocation.FLAG_PRIORITY_NETWORK; + flag |= NSRealtimeLocation.FLAG_PRIORITY_GPS; + } + realtimeLocation.Init(flag); + } + long start = System.currentTimeMillis(); + loc = realtimeLocation.Read(preference.GetIntFromString(NSPreference.LOCATION_REALTIME_READ_COUNT, NSConstants.DEFAULT_LOCATION_REALTIME_READ_COUNT)); + long end = System.currentTimeMillis(); + Log.i(ID_TAG, "系统实时定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); + } + catch(Throwable e) + { + e.printStackTrace(); + } + return loc; + } + + public NSLocationInfo GetAMapLocation() + { + Log.i(ID_TAG, "使用高德定位"); + NSLocationInfo loc = null; + try + { + NSPreference preference = new NSPreference(m_context); + if(!amapLocation.IsInitialized()) + { + amapLocation.SetOption(NSAMapLocation.OPTION_INTERVAL, preference.GetIntFromString(NSPreference.LOCATION_GAODE_INTERVAL, NSConstants.DEFAULT_LOCATION_GAODE_INTERVAL)); + amapLocation.Init(NSAMapLocation.DEFAULT_FLAG | NSAMapLocation.FLAG_BUILTIN_THREAD); + } + long start = System.currentTimeMillis(); + loc = amapLocation.Read(preference.GetIntFromString(NSPreference.LOCATION_GAODE_READ_COUNT, NSConstants.DEFAULT_LOCATION_GAODE_READ_COUNT)); + long end = System.currentTimeMillis(); + Log.i(ID_TAG, "高德定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); + } + catch(Throwable e) + { + e.printStackTrace(); + } + return loc; + } + + private boolean CheckLocationPermission() + { + if(ActivityCompat.checkSelfPermission(m_context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(m_context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) + { + Activity activity = (Activity) m_context; + + if (activity.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION) && activity.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_COARSE_LOCATION)) // do not ask + { + Toast.makeText(m_context, "请先允许定位服务", Toast.LENGTH_LONG).show(); + NSContextUtils.RequestLocationPermission(activity, FullscreenActivity.PERMISSION_LOCATION_REQUEST_CODE); + } + else + { + activity.requestPermissions(new String[] { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }, FullscreenActivity.PERMISSION_LOCATION_REQUEST_CODE); + } + + return false; + } + else + return true; + } + + protected void RunOnUIThread(Runnable runnable) + { + if(null != m_handler) + m_handler.post(runnable); + else if(m_context instanceof Activity) + ((Activity)m_context).runOnUiThread(runnable); + else + { + Log.e(ID_TAG, "无法在UI线程中执行"); + } + } + + protected void CallJSFunc(final String func, Object...args) + { + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < args.length; i++) + { + sb.append("'").append(args[i].toString()).append("'"); + if(i < args.length - 1) + sb.append(", "); + } + final String arg = sb.toString(); + RunOnUIThread(new Runnable() { + @Override + public void run() + { + String script = "javascript:typeof(" + func + ") == 'function' && " + func + "(" + arg + ");"; + Log.e(ID_TAG, String.format("调用js函数: 函数(%s), 参数(%s)", func, arg)); + m_webView.evaluateJavascript(script, new ValueCallback() { + @Override + public void onReceiveValue(String value) { + Log.e(ID_TAG, String.format("js函数 %s 返回: %s", func, value)); + } + }); + } + }); + } + + protected void CallJSFunc_beforeAndroid4_4(final String func, Object...args) + { + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < args.length; i++) + { + sb.append("'").append(args[i].toString()).append("'"); + if(i < args.length - 1) + sb.append(", "); + } + final String arg = sb.toString(); + RunOnUIThread(new Runnable() { + @Override + public void run() { + Log.e(ID_TAG, String.format("调用js函数: 函数(%s), 参数(%s)", func, arg)); + String script = "javascript:typeof(" + func + ") == 'function' && " + func + "(" + arg + ");"; + Log.e(ID_TAG, script); + m_webView.loadUrl(script, null); + } + }); + } +} \ No newline at end of file