| @@ -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 | |||||
| ; | |||||
| } | |||||
| } | |||||
| @@ -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<Integer, Object> 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> T GetOption(int type, T def) | |||||
| { | |||||
| Object o = m_options.get(type); | |||||
| if(null == o) | |||||
| return def; | |||||
| return (T) o; | |||||
| } | |||||
| private void InitOptions() | |||||
| { | |||||
| List<String> 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(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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<String> allProviders = lm.getAllProviders(); | |||||
| Log.i(ID_TAG, "使用最近所有定位提供器: " + allProviders); | |||||
| Map<String, NSLocationInfo> 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<Location> 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; | |||||
| } | |||||
| } | |||||
| @@ -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<String>() { | |||||
| @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); | |||||
| } | |||||
| }); | |||||
| } | |||||
| } | |||||