@@ -25,12 +25,13 @@ | |||||
* 使用Android Studio生成签名包 | * 使用Android Studio生成签名包 | ||||
* 配置```appCopyright=```启动页版权文本, 不要加双引号 | * 配置```appCopyright=```启动页版权文本, 不要加双引号 | ||||
* 配置```appVendor=```启动页厂商名称, 不要加双引号 | * 配置```appVendor=```启动页厂商名称, 不要加双引号 | ||||
* 配置```appUpdateUrl=```apk下载更新地址, 不要加双引号 | |||||
* 生成的apk路径为 `/app/release/app-release.apk` | * 生成的apk路径为 `/app/release/app-release.apk` | ||||
> 使用`gradle`脚本打签名的正式包 | > 使用`gradle`脚本打签名的正式包 | ||||
* 执行 ```gradlew assembleRelease``` 将使用`gradle.properties`文件里的配置进行打包 | * 执行 ```gradlew assembleRelease``` 将使用`gradle.properties`文件里的配置进行打包 | ||||
* 如果需要自定义配置(无需修改`gradle.properties`文件), 执行 ```gradlew assembleRelease -PappHomeUrl="首页地址" -PappName="App桌面快捷方式名称(只能使用字符串)" -PappIconKey="图标名称" -PappIconKey="启动页版权文本" -PappCopyright="启动页厂商名称"``` 将使用命令行里的配置进行打包 | |||||
* 如果需要自定义配置(无需修改`gradle.properties`文件), 执行 ```gradlew assembleRelease -PappHomeUrl="首页地址" -PappName="App桌面快捷方式名称(只能使用字符串)" -PappIconKey="图标名称" -PappIconKey="启动页版权文本" -PappCopyright="启动页厂商名称" -PappUpdateUrl="apk下载更新地址"``` 将使用命令行里的配置进行打包 | |||||
* 生成的apk路径为 `/app/build/outputs/apk/release/app-release.apk` | * 生成的apk路径为 `/app/build/outputs/apk/release/app-release.apk` | ||||
> 帮助脚本 | > 帮助脚本 | ||||
@@ -10,7 +10,7 @@ android { | |||||
minSdkVersion 24 | minSdkVersion 24 | ||||
targetSdkVersion 30 | targetSdkVersion 30 | ||||
versionCode 1 | versionCode 1 | ||||
versionName "1.0" | |||||
versionName "1.0.0.1" | |||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||||
@@ -25,6 +25,9 @@ android { | |||||
// App图标 | // App图标 | ||||
buildConfigField "String", "APP_ICON", "\"${project.properties.appIconKey}\"" | buildConfigField "String", "APP_ICON", "\"${project.properties.appIconKey}\"" | ||||
// App更新下载地址 | |||||
buildConfigField "String", "APP_UPDATE_URL", "\"${project.properties.appUpdateUrl}\"" | |||||
// AndroidManifest.xml占位符 | // AndroidManifest.xml占位符 | ||||
manifestPlaceholders = [ | manifestPlaceholders = [ | ||||
// App名称 | // App名称 | ||||
@@ -32,7 +35,9 @@ android { | |||||
// App图标 | // App图标 | ||||
APP_ICON: "@mipmap/ic_launcher_${project.properties.appIconKey}", | APP_ICON: "@mipmap/ic_launcher_${project.properties.appIconKey}", | ||||
// App圆角图标 | // App圆角图标 | ||||
APP_ROUND_ICON: "@mipmap/ic_launcher_${project.properties.appIconKey}_round" | |||||
APP_ROUND_ICON: "@mipmap/ic_launcher_${project.properties.appIconKey}_round", | |||||
// 高德key | |||||
AMAP_KEY: "${project.properties.amapKey}", | |||||
] | ] | ||||
} | } | ||||
@@ -56,6 +61,7 @@ android { | |||||
resValue("string", "app_copyright", "\"${project.properties.appCopyright}\"") | resValue("string", "app_copyright", "\"${project.properties.appCopyright}\"") | ||||
resValue("string", "app_vendor", "\"${project.properties.appVendor}\"") | resValue("string", "app_vendor", "\"${project.properties.appVendor}\"") | ||||
resValue("string", "app_name2", "\"${project.properties.appName}\"") | resValue("string", "app_name2", "\"${project.properties.appName}\"") | ||||
resValue("string", "app_update_url", "\"${project.properties.appUpdateUrl}\"") | |||||
} | } | ||||
debug { | debug { | ||||
signingConfig signingConfigs.release | signingConfig signingConfigs.release | ||||
@@ -63,6 +69,7 @@ android { | |||||
resValue("string", "app_copyright", "\"${project.properties.appCopyright}\"") | resValue("string", "app_copyright", "\"${project.properties.appCopyright}\"") | ||||
resValue("string", "app_vendor", "\"${project.properties.appVendor}\"") | resValue("string", "app_vendor", "\"${project.properties.appVendor}\"") | ||||
resValue("string", "app_name2", "\"${project.properties.appName}\"") | resValue("string", "app_name2", "\"${project.properties.appName}\"") | ||||
resValue("string", "app_update_url", "\"${project.properties.appUpdateUrl}\"") | |||||
} | } | ||||
} | } | ||||
compileOptions { | compileOptions { | ||||
@@ -48,7 +48,7 @@ | |||||
android:theme="@style/Theme.Nsgk_rural_web"> | android:theme="@style/Theme.Nsgk_rural_web"> | ||||
<meta-data | <meta-data | ||||
android:name="com.amap.api.v2.apikey" | android:name="com.amap.api.v2.apikey" | ||||
android:value="7e6911ad842a6a6f492d27efdbd42f30"/> | |||||
android:value="${AMAP_KEY}"/> | |||||
<activity | <activity | ||||
android:name=".WelcomeActivity" | android:name=".WelcomeActivity" | ||||
@@ -80,6 +80,20 @@ | |||||
</receiver> | </receiver> | ||||
--> | --> | ||||
<service android:name="com.amap.api.location.APSService"></service> | <service android:name="com.amap.api.location.APSService"></service> | ||||
<provider | |||||
android:name="androidx.core.content.FileProvider" | |||||
android:authorities="${applicationId}.fileprovider" | |||||
android:exported="false" | |||||
android:grantUriPermissions="true" | |||||
android:permission="android.permission.MANAGE_DOCUMENTS"> | |||||
<!-- <intent-filter> | |||||
<action android:name="android.content.action.DOCUMENTS_PROVIDER" /> | |||||
</intent-filter>--> | |||||
<meta-data | |||||
android:name="android.support.FILE_PROVIDER_PATHS" | |||||
android:resource="@xml/file_paths" /> | |||||
</provider> | |||||
</application> | </application> | ||||
</manifest> | </manifest> |
@@ -10,6 +10,7 @@ import android.os.Bundle; | |||||
import android.os.Handler; | import android.os.Handler; | ||||
import android.util.Log; | import android.util.Log; | ||||
import android.view.KeyEvent; | import android.view.KeyEvent; | ||||
import android.view.View; | |||||
import android.view.ViewGroup; | import android.view.ViewGroup; | ||||
import android.webkit.ConsoleMessage; | import android.webkit.ConsoleMessage; | ||||
import android.webkit.GeolocationPermissions; | import android.webkit.GeolocationPermissions; | ||||
@@ -18,6 +19,7 @@ import android.webkit.WebHistoryItem; | |||||
import android.webkit.WebSettings; | import android.webkit.WebSettings; | ||||
import android.webkit.WebView; | import android.webkit.WebView; | ||||
import android.widget.LinearLayout; | import android.widget.LinearLayout; | ||||
import android.widget.ProgressBar; | |||||
import android.widget.RelativeLayout; | import android.widget.RelativeLayout; | ||||
import android.widget.Toast; | import android.widget.Toast; | ||||
@@ -54,6 +56,7 @@ public class FullscreenActivity extends AppCompatActivity { | |||||
private String m_lastUrl; | private String m_lastUrl; | ||||
private String m_mainUrl; | private String m_mainUrl; | ||||
private View m_progressIndicator; | |||||
@SuppressLint("SetJavaScriptEnabled") | @SuppressLint("SetJavaScriptEnabled") | ||||
@Override | @Override | ||||
@@ -167,6 +170,18 @@ public class FullscreenActivity extends AppCompatActivity { | |||||
mAgentWeb.getJsInterfaceHolder().addJavaObject("_Native_object", envWindowObject); | mAgentWeb.getJsInterfaceHolder().addJavaObject("_Native_object", envWindowObject); | ||||
mAgentWeb.getJsInterfaceHolder().addJavaObject("Android", envWindowObject); | mAgentWeb.getJsInterfaceHolder().addJavaObject("Android", envWindowObject); | ||||
// 等待条指示器 | |||||
m_progressIndicator = getLayoutInflater().inflate(R.layout.location_indicator, null); | |||||
m_progressIndicator.findViewById(R.id.terminate_button).setOnClickListener((View view) -> { | |||||
envWindowObject.TerminateLocation(); | |||||
}); | |||||
m_progressIndicator.setVisibility(View.GONE); | |||||
m_progressIndicator.setZ(99); | |||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); | |||||
params.addRule(RelativeLayout.CENTER_IN_PARENT); | |||||
((RelativeLayout)findViewById(R.id.ll)).addView(m_progressIndicator, params); | |||||
/* 上边url是各个APP项目的入口地址 | /* 上边url是各个APP项目的入口地址 | ||||
事项审批 http://116.255.223.226:82/yinnongLogin 图标 ic_launcher_sxsp 或者 ic_launcher_yhzl | 事项审批 http://116.255.223.226:82/yinnongLogin 图标 ic_launcher_sxsp 或者 ic_launcher_yhzl | ||||
阳光村务(村级事项) http://116.255.223.226:82/sunVillage_info/login 图标 ic_launcher_ygcw | 阳光村务(村级事项) http://116.255.223.226:82/sunVillage_info/login 图标 ic_launcher_ygcw | ||||
@@ -215,16 +230,21 @@ public class FullscreenActivity extends AppCompatActivity { | |||||
@Override | @Override | ||||
public boolean onKeyDown(int keyCode, KeyEvent event) { | public boolean onKeyDown(int keyCode, KeyEvent event) { | ||||
// if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) { | |||||
// mWebView.goBack(); | |||||
// return true; | |||||
// } | |||||
if (keyCode == KeyEvent.KEYCODE_BACK && HandleBackKeyEvent(1)) { | |||||
return true; | |||||
} | |||||
if (mAgentWeb.handleKeyEvent(keyCode, event)) { | if (mAgentWeb.handleKeyEvent(keyCode, event)) { | ||||
return true; | return true; | ||||
} | } | ||||
return super.onKeyDown(keyCode, event); | return super.onKeyDown(keyCode, event); | ||||
} | } | ||||
@Override | |||||
public void onBackPressed() | |||||
{ | |||||
if(!HandleBackKeyEvent(2)) | |||||
super.onBackPressed(); | |||||
} | |||||
@Override | @Override | ||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { | ||||
@@ -250,19 +270,6 @@ public class FullscreenActivity extends AppCompatActivity { | |||||
} | } | ||||
} | } | ||||
@Override | |||||
public void onBackPressed() | |||||
{ | |||||
WebView webView = GetWebView(); | |||||
if (null != webView && !webView.canGoBack() && !IsInDefaultPage()) { | |||||
webView.loadUrl(NSConstants.AppHomeUrl()); | |||||
webView.clearHistory(); | |||||
//History(); | |||||
return; | |||||
} | |||||
super.onBackPressed(); | |||||
} | |||||
private NSPreference GetPreference() | private NSPreference GetPreference() | ||||
{ | { | ||||
if(null == preference) | if(null == preference) | ||||
@@ -337,4 +344,38 @@ public class FullscreenActivity extends AppCompatActivity { | |||||
Log.d(ID_TAG, StrUtil.format("{}: {} {}", i, item.getTitle(), item.getUrl())); | Log.d(ID_TAG, StrUtil.format("{}: {} {}", i, item.getTitle(), item.getUrl())); | ||||
} | } | ||||
} | } | ||||
public void SetIndicatorVisible(boolean on) | |||||
{ | |||||
m_progressIndicator.setVisibility(on ? View.VISIBLE : View.GONE); | |||||
} | |||||
private boolean HandleBackKeyEvent(int from) | |||||
{ | |||||
if(!IsRecordUrl()) | |||||
return false; | |||||
WebView webView = GetWebView(); | |||||
if(null == webView) | |||||
return false; | |||||
boolean inDefaultPage = IsInDefaultPage(); | |||||
//System.err.println(m_lastUrl +" -> " + inDefaultPage + " = " + webView.canGoBack()); | |||||
if(inDefaultPage) | |||||
{ | |||||
if(from == 1 && !webView.canGoBack()) | |||||
{ | |||||
finish(); | |||||
return true; | |||||
} | |||||
else | |||||
return false; | |||||
} | |||||
if (!webView.canGoBack() && !inDefaultPage) { | |||||
webView.loadUrl(NSConstants.AppHomeUrl()); | |||||
webView.clearHistory(); | |||||
//History(); | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
} | } |
@@ -186,7 +186,7 @@ public class NSAMapLocation implements AMapLocationListener | |||||
//设置场景模式后最好调用一次stop,再调用start以保证场景模式生效 | //设置场景模式后最好调用一次stop,再调用start以保证场景模式生效 | ||||
mLocationClient.stopLocation(); | mLocationClient.stopLocation(); | ||||
Log.i(ID_TAG, "定位停止"); | |||||
Log.i(ID_TAG, "高德定位停止"); | |||||
} | } | ||||
public void Shutdown() | public void Shutdown() | ||||
@@ -197,6 +197,7 @@ public class NSAMapLocation implements AMapLocationListener | |||||
return; | return; | ||||
} | } | ||||
TerminateRead(); | |||||
Stop(); | Stop(); | ||||
mLocationClient.onDestroy(); | mLocationClient.onDestroy(); | ||||
@@ -205,10 +206,10 @@ public class NSAMapLocation implements AMapLocationListener | |||||
{ | { | ||||
m_thread.quit(); | m_thread.quit(); | ||||
m_thread = null; | m_thread = null; | ||||
Log.d(ID_TAG, "内建线程结束"); | |||||
Log.d(ID_TAG, "高德定位内建线程结束"); | |||||
} | } | ||||
Log.i(ID_TAG, "定位销毁"); | |||||
Log.i(ID_TAG, "高德定位销毁"); | |||||
} | } | ||||
public void PreInit() | public void PreInit() | ||||
@@ -346,8 +347,7 @@ public class NSAMapLocation implements AMapLocationListener | |||||
@Override | @Override | ||||
public void onLocationChanged(AMapLocation amapLocation) | public void onLocationChanged(AMapLocation amapLocation) | ||||
{ | { | ||||
Log.d(ID_TAG, "onLocationChanged线程: " + Thread.currentThread().getId()); | |||||
System.err.println(amapLocation); | |||||
Log.d(ID_TAG, "AMap定位回调线程: " + Thread.currentThread().getId() + " -> " + amapLocation); | |||||
SetLastLocation(amapLocation); | SetLastLocation(amapLocation); | ||||
if(null != amapLocation) | if(null != amapLocation) | ||||
{ | { | ||||
@@ -446,6 +446,15 @@ public class NSAMapLocation implements AMapLocationListener | |||||
return m_lastLocation; | return m_lastLocation; | ||||
} | } | ||||
public void TerminateRead() | |||||
{ | |||||
synchronized(m_lock) | |||||
{ | |||||
Log.i(ID_TAG, "AMap中止定位"); | |||||
m_lock.notifyAll(); | |||||
} | |||||
} | |||||
public void CleanLastLocation() | public void CleanLastLocation() | ||||
{ | { | ||||
m_lastLocation = null; | m_lastLocation = null; | ||||
@@ -0,0 +1,84 @@ | |||||
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.os.CancellationSignal; | |||||
import android.util.Log; | |||||
import android.widget.Toast; | |||||
import com.nsgk.ruralWeb.sys.NSConstants; | |||||
import java.util.HashMap; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.concurrent.CompletableFuture; | |||||
import java.util.concurrent.TimeUnit; | |||||
public class NSLastKnownLocation | |||||
{ | |||||
private static final String ID_TAG = NSLastKnownLocation.class.getName(); | |||||
private final Context m_context; | |||||
private NSLocationInfo m_lastLocation = null; | |||||
public NSLastKnownLocation(Context context) | |||||
{ | |||||
m_context = context; | |||||
} | |||||
@SuppressLint("MissingPermission") | |||||
public NSLocationInfo Read(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(NSConstants.FUSED_PROVIDER)) | |||||
loc = map.get(NSConstants.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); | |||||
m_lastLocation = loc; | |||||
} | |||||
} | |||||
catch(Throwable e) | |||||
{ | |||||
e.printStackTrace(); | |||||
} | |||||
return loc; | |||||
} | |||||
public NSLocationInfo GetLastLocation() | |||||
{ | |||||
return m_lastLocation; | |||||
} | |||||
} |
@@ -159,7 +159,7 @@ public class NSRealtimeLocation implements LocationListener | |||||
m_locationManager.removeUpdates(this); | m_locationManager.removeUpdates(this); | ||||
m_provider = null; | m_provider = null; | ||||
Log.i(ID_TAG, "定位停止"); | |||||
Log.i(ID_TAG, "实时定位停止"); | |||||
} | } | ||||
public void Shutdown() | public void Shutdown() | ||||
@@ -170,6 +170,7 @@ public class NSRealtimeLocation implements LocationListener | |||||
return; | return; | ||||
} | } | ||||
TerminateRead(); | |||||
Stop(); | Stop(); | ||||
m_locationManager = null; | m_locationManager = null; | ||||
@@ -177,10 +178,10 @@ public class NSRealtimeLocation implements LocationListener | |||||
{ | { | ||||
m_thread.quit(); | m_thread.quit(); | ||||
m_thread = null; | m_thread = null; | ||||
Log.d(ID_TAG, "内建线程结束"); | |||||
Log.d(ID_TAG, "实时定位内建线程结束"); | |||||
} | } | ||||
Log.i(ID_TAG, "定位销毁"); | |||||
Log.i(ID_TAG, "实时定位销毁"); | |||||
} | } | ||||
public boolean IsInitialized() | public boolean IsInitialized() | ||||
@@ -350,8 +351,7 @@ public class NSRealtimeLocation implements LocationListener | |||||
@Override | @Override | ||||
public void onLocationChanged(@NonNull Location location) | public void onLocationChanged(@NonNull Location location) | ||||
{ | { | ||||
Log.d(ID_TAG, "onLocationChanged线程: " + Thread.currentThread().getId()); | |||||
System.err.println(location); | |||||
Log.d(ID_TAG, "系统实时定位线程: " + Thread.currentThread().getId() + " -> " + location); | |||||
SetLastLocation(location); | SetLastLocation(location); | ||||
//if(null != location) | //if(null != location) | ||||
{ | { | ||||
@@ -368,4 +368,13 @@ public class NSRealtimeLocation implements LocationListener | |||||
} | } | ||||
} | } | ||||
} | } | ||||
public void TerminateRead() | |||||
{ | |||||
synchronized(m_lock) | |||||
{ | |||||
Log.i(ID_TAG, "系统实时中止定位"); | |||||
m_lock.notifyAll(); | |||||
} | |||||
} | |||||
} | } |
@@ -7,6 +7,7 @@ import android.location.Criteria; | |||||
import android.location.Location; | import android.location.Location; | ||||
import android.location.LocationManager; | import android.location.LocationManager; | ||||
import android.os.Build; | import android.os.Build; | ||||
import android.os.CancellationSignal; | |||||
import android.util.Log; | import android.util.Log; | ||||
import android.widget.Toast; | import android.widget.Toast; | ||||
@@ -14,92 +15,28 @@ import java.util.HashMap; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.concurrent.CompletableFuture; | import java.util.concurrent.CompletableFuture; | ||||
import java.util.concurrent.TimeUnit; | |||||
public class NSSystemLocation | public class NSSystemLocation | ||||
{ | { | ||||
private static final String ID_TAG = NSSystemLocation.class.getName(); | private static final String ID_TAG = NSSystemLocation.class.getName(); | ||||
public static final String FUSED_PROVIDER = "fused"; | |||||
private final Context m_context; | private final Context m_context; | ||||
private NSLocationInfo m_lastLocation = null; | private NSLocationInfo m_lastLocation = null; | ||||
private volatile CancellationSignal m_cancellationSignal; | |||||
private volatile CompletableFuture<Location> m_future; | |||||
public NSSystemLocation(Context context) | public NSSystemLocation(Context context) | ||||
{ | { | ||||
m_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") | @SuppressLint("MissingPermission") | ||||
private NSLocationInfo GetHighLocation(String provider) | |||||
public NSLocationInfo Read(String provider, int timeout) | |||||
{ | { | ||||
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R) | if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R) | ||||
{ | { | ||||
Log.w(ID_TAG, "获取当前定位请求Android 11+"); | |||||
return null; | return null; | ||||
} | } | ||||
@@ -153,9 +90,16 @@ public class NSSystemLocation | |||||
return null; | return null; | ||||
} | } | ||||
CompletableFuture<Location> future = new CompletableFuture<>(); | |||||
lm.getCurrentLocation(provider, null, m_context.getMainExecutor(), future::complete); | |||||
Location location = future.get(); | |||||
m_cancellationSignal = new CancellationSignal(); | |||||
m_future = new CompletableFuture<>(); | |||||
lm.getCurrentLocation(provider, m_cancellationSignal, m_context.getMainExecutor(), m_future::complete); | |||||
Location location; | |||||
if(timeout > 0) | |||||
location = m_future.get(timeout, TimeUnit.MILLISECONDS); | |||||
else | |||||
location = m_future.get(); | |||||
m_cancellationSignal = null; | |||||
m_future = null; | |||||
if(null == location) | if(null == location) | ||||
{ | { | ||||
Log.i(ID_TAG, "无法使用高精度提供器定位"); | Log.i(ID_TAG, "无法使用高精度提供器定位"); | ||||
@@ -163,11 +107,17 @@ public class NSSystemLocation | |||||
} | } | ||||
loc = new NSLocationInfo(provider, location.getLongitude(), location.getLatitude()); | loc = new NSLocationInfo(provider, location.getLongitude(), location.getLatitude()); | ||||
Log.i(ID_TAG, "使用高精度提供器获取定位: " + loc); | Log.i(ID_TAG, "使用高精度提供器获取定位: " + loc); | ||||
m_lastLocation = loc; | |||||
} | } | ||||
catch(Throwable e) | catch(Throwable e) | ||||
{ | { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
} | } | ||||
finally | |||||
{ | |||||
m_cancellationSignal = null; | |||||
m_future = null; | |||||
} | |||||
return loc; | return loc; | ||||
} | } | ||||
@@ -182,6 +132,28 @@ public class NSSystemLocation | |||||
})); | })); | ||||
} | } | ||||
public void TerminateRead() | |||||
{ | |||||
CancellationSignal signal = m_cancellationSignal; | |||||
if(null != signal && !signal.isCanceled()) | |||||
{ | |||||
Log.i(ID_TAG, "系统中止定位: 1. 取消定位"); | |||||
signal.cancel(); | |||||
} | |||||
CompletableFuture<Location> future = m_future; | |||||
if(null != future && !future.isCancelled()) | |||||
{ | |||||
Log.i(ID_TAG, "系统中止定位: 2. 取消等待结果"); | |||||
future.cancel(true); | |||||
} | |||||
} | |||||
public void Shutdown() | |||||
{ | |||||
Log.i(ID_TAG, "销毁系统定位"); | |||||
TerminateRead(); | |||||
} | |||||
public NSLocationInfo GetLastLocation() | public NSLocationInfo GetLastLocation() | ||||
{ | { | ||||
return m_lastLocation; | return m_lastLocation; | ||||
@@ -37,16 +37,39 @@ public final class NSConstants | |||||
return BuildConfig.APP_VENDOR; | return BuildConfig.APP_VENDOR; | ||||
} | } | ||||
/** | |||||
* App图标 | |||||
*/ | |||||
public static String AppIcon() | public static String AppIcon() | ||||
{ | { | ||||
return BuildConfig.APP_ICON; | return BuildConfig.APP_ICON; | ||||
} | } | ||||
/** | |||||
* App更新下载地址 | |||||
* 可以在 /gradle.properties 里配置 appUpdateUrl=链接地址, 不要携带双引号 | |||||
* 也可以在命令行添加 -PappUpdateUrl="链接地址", 双引号可携带也可不携带 | |||||
*/ | |||||
public static String AppUpdateUrl() | |||||
{ | |||||
return BuildConfig.APP_UPDATE_URL; | |||||
} | |||||
public static boolean IsHttps() | public static boolean IsHttps() | ||||
{ | { | ||||
return AppHomeUrl().startsWith("https://"); | return AppHomeUrl().startsWith("https://"); | ||||
} | } | ||||
public static boolean IsDebug() | |||||
{ | |||||
return BuildConfig.DEBUG; | |||||
} | |||||
public static boolean IsAMapLocationEnabled() | |||||
{ | |||||
return true; | |||||
} | |||||
// 偏好默认值 | // 偏好默认值 | ||||
public static final String DEFAULT_LOCATION_MODE = NSEnums.LocationMode.REALTIME; | public static final String DEFAULT_LOCATION_MODE = NSEnums.LocationMode.REALTIME; | ||||
public static final int DEFAULT_LOCATION_GAODE_INTERVAL = 1000; | public static final int DEFAULT_LOCATION_GAODE_INTERVAL = 1000; | ||||
@@ -60,5 +83,10 @@ public final class NSConstants | |||||
public static final boolean DEFAULT_LOGCAT_CONSOLE_OUTPUT = false; | public static final boolean DEFAULT_LOGCAT_CONSOLE_OUTPUT = false; | ||||
public static final int DEFAULT_LOCATION_TIMEOUT = 0; | public static final int DEFAULT_LOCATION_TIMEOUT = 0; | ||||
public static final String FUSED_PROVIDER = "fused"; | |||||
public static final String APK_UPDATE_DOWNLOAD_DIR = "update"; | |||||
public static final String APK_UPDATE_DOWNLOAD_FILE = "latest.apk"; | |||||
private NSConstants() {} | private NSConstants() {} | ||||
} | } |
@@ -19,10 +19,11 @@ public final class NSPreference | |||||
public static final String LAST_ACCESS_URL = "last_access_url"; | public static final String LAST_ACCESS_URL = "last_access_url"; | ||||
public static final String COOKIES = "cookies"; | public static final String COOKIES = "cookies"; | ||||
public static final String FONT_SCALE = "font_scale"; | public static final String FONT_SCALE = "font_scale"; | ||||
public static final String LOGCAT_CONSOLE_OUTPUT = "logcat_console_output"; | |||||
public static final String LOGCAT_CONSOLE_OUTPUT = "logcat_console_output"; | |||||
public static final String LOCATION_TIMEOUT = "location_timeout"; | public static final String LOCATION_TIMEOUT = "location_timeout"; | ||||
public static final String RESET_SETTINGS = "RESET_SETTINGS"; | public static final String RESET_SETTINGS = "RESET_SETTINGS"; | ||||
public static final String VERSION = "VERSION"; | public static final String VERSION = "VERSION"; | ||||
public static final String UPDATE_DOWNLOAD = "UPDATE_DOWNLOAD"; | |||||
private final Context context; | private final Context context; | ||||
@@ -2,8 +2,14 @@ package com.nsgk.ruralWeb.ui; | |||||
import android.content.Context; | import android.content.Context; | ||||
import android.content.DialogInterface; | import android.content.DialogInterface; | ||||
import android.content.Intent; | |||||
import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||
import android.net.Uri; | |||||
import android.os.Bundle; | import android.os.Bundle; | ||||
import android.os.Handler; | |||||
import android.os.HandlerThread; | |||||
import android.os.Looper; | |||||
import android.provider.Settings; | |||||
import android.text.Html; | import android.text.Html; | ||||
import android.util.Log; | import android.util.Log; | ||||
import android.widget.Toast; | import android.widget.Toast; | ||||
@@ -23,10 +29,13 @@ import com.nsgk.ruralWeb.utils.NSContextUtils; | |||||
import com.nsgk.ruralWeb.utils.NSMisc; | import com.nsgk.ruralWeb.utils.NSMisc; | ||||
import com.nsgk.ruralWeb.utils.NSStr; | import com.nsgk.ruralWeb.utils.NSStr; | ||||
import java.io.File; | |||||
import java.util.Objects; | import java.util.Objects; | ||||
import cn.hutool.core.io.FileUtil; | |||||
import cn.hutool.core.util.NumberUtil; | import cn.hutool.core.util.NumberUtil; | ||||
import cn.hutool.core.util.StrUtil; | import cn.hutool.core.util.StrUtil; | ||||
import cn.hutool.http.HttpUtil; | |||||
public class SettingsFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener | public class SettingsFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener | ||||
{ | { | ||||
@@ -88,8 +97,17 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Prefer | |||||
preference = findPreference(NSPreference.VERSION); | preference = findPreference(NSPreference.VERSION); | ||||
preference.setOnPreferenceClickListener(this); | preference.setOnPreferenceClickListener(this); | ||||
preference = findPreference("location_gaode"); | |||||
preference.setVisible(false); | |||||
preference = findPreference(NSPreference.UPDATE_DOWNLOAD); | |||||
preference.setOnPreferenceClickListener(this); | |||||
if(StrUtil.isBlank(NSConstants.AppUpdateUrl())) | |||||
preference.setVisible(false); | |||||
// 总是隐藏高德的设置 | |||||
if(!NSConstants.IsAMapLocationEnabled() || !NSContextUtils.BuildIsDebug(context)) | |||||
{ | |||||
preference = findPreference("location_gaode"); | |||||
preference.setVisible(false); | |||||
} | |||||
} | } | ||||
private boolean CheckValueIsNumber(Object newValue, Integer min) | private boolean CheckValueIsNumber(Object newValue, Integer min) | ||||
@@ -164,7 +182,7 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Prefer | |||||
break; | break; | ||||
} | } | ||||
case NSPreference.LOCATION_MODE: | case NSPreference.LOCATION_MODE: | ||||
if(Objects.equals(NSEnums.LocationMode.GAODE, newValue)) | |||||
if(!NSConstants.IsAMapLocationEnabled() && Objects.equals(NSEnums.LocationMode.GAODE, newValue)) | |||||
{ | { | ||||
Log.w(ID_TAG, "高德定位被禁用"); | Log.w(ID_TAG, "高德定位被禁用"); | ||||
return false; | return false; | ||||
@@ -202,10 +220,63 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Prefer | |||||
case NSPreference.VERSION: | case NSPreference.VERSION: | ||||
OpenAbout(); | OpenAbout(); | ||||
break; | break; | ||||
case NSPreference.UPDATE_DOWNLOAD: | |||||
DownloadUpdate(); | |||||
//DownloadUpdateExternally(); | |||||
break; | |||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
private void DownloadUpdateExternally() | |||||
{ | |||||
String updateUrl = NSConstants.AppUpdateUrl(); | |||||
if(StrUtil.isBlank(updateUrl)) | |||||
return; | |||||
Context context = getContext(); | |||||
Toast.makeText(context, "正在打开下载地址......", Toast.LENGTH_SHORT).show(); | |||||
NSContextUtils.OpenUrlExternally(context, updateUrl); | |||||
} | |||||
private void DownloadUpdate() | |||||
{ | |||||
String updateUrl = NSConstants.AppUpdateUrl(); | |||||
if(StrUtil.isBlank(updateUrl)) | |||||
return; | |||||
Handler handler = new Handler(Looper.myLooper()); | |||||
Context context = getContext(); | |||||
Log.d(ID_TAG, "下载apk地址: " + updateUrl); | |||||
Toast.makeText(context, "开始下载......", Toast.LENGTH_SHORT).show(); | |||||
// 创建文件夹并删除缓存文件 | |||||
File externalFilesDir = context.getExternalFilesDir(null); | |||||
String dir = externalFilesDir.getAbsolutePath() + File.separator + NSConstants.APK_UPDATE_DOWNLOAD_DIR; | |||||
FileUtil.mkdir(dir); | |||||
String file = dir + File.separator + NSConstants.APK_UPDATE_DOWNLOAD_FILE; | |||||
Log.d(ID_TAG, "删除文件: " + file); | |||||
FileUtil.del(file); | |||||
new Thread(() -> { | |||||
long bytes = HttpUtil.downloadFile(updateUrl, file); | |||||
Log.d(ID_TAG, "下载apk文件: " + FileUtil.readableFileSize(bytes)); | |||||
if(bytes > 0) | |||||
{ | |||||
handler.post(() -> { | |||||
Toast.makeText(context, "准备安装......", Toast.LENGTH_SHORT).show(); | |||||
NSContextUtils.InstallApk(context, file); | |||||
}); | |||||
} | |||||
else | |||||
{ | |||||
handler.post(() -> { | |||||
Toast.makeText(context, "下载更新失败", Toast.LENGTH_LONG).show(); | |||||
}); | |||||
} | |||||
}).start(); | |||||
} | |||||
private void ResetSettings() | private void ResetSettings() | ||||
{ | { | ||||
NSPreference preference = new NSPreference(getContext()); | NSPreference preference = new NSPreference(getContext()); | ||||
@@ -8,7 +8,15 @@ import android.content.pm.PackageInfo; | |||||
import android.content.pm.PackageManager; | import android.content.pm.PackageManager; | ||||
import android.content.res.Resources; | import android.content.res.Resources; | ||||
import android.net.Uri; | import android.net.Uri; | ||||
import android.os.Build; | |||||
import android.provider.Settings; | import android.provider.Settings; | ||||
import android.widget.Toast; | |||||
import androidx.core.content.FileProvider; | |||||
import com.nsgk.ruralWeb.sys.NSConstants; | |||||
import java.io.File; | |||||
public final class NSContextUtils | public final class NSContextUtils | ||||
{ | { | ||||
@@ -42,20 +50,6 @@ public final class NSContextUtils | |||||
return version; | return version; | ||||
} | } | ||||
public static boolean BuildIsDebug(Context context) | |||||
{ | |||||
try | |||||
{ | |||||
ApplicationInfo info = context.getApplicationInfo(); | |||||
return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
e.printStackTrace(); | |||||
return false; // default is release | |||||
} | |||||
} | |||||
public static String GetListName(Context context, String value, int keyResource, int nameResource, String... def) | public static String GetListName(Context context, String value, int keyResource, int nameResource, String... def) | ||||
{ | { | ||||
Resources resources = context.getResources(); | Resources resources = context.getResources(); | ||||
@@ -75,5 +69,54 @@ public final class NSContextUtils | |||||
return context.getResources().getString(id, args); | return context.getResources().getString(id, args); | ||||
} | } | ||||
public static void OpenUrlExternally(Context context, String url) | |||||
{ | |||||
Uri uri = Uri.parse(url); | |||||
Intent intent = new Intent(Intent.ACTION_VIEW, uri); | |||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); | |||||
context.startActivity(intent); | |||||
} | |||||
public static void InstallApk(Context context, String apkFile) | |||||
{ | |||||
File file = new File(apkFile); | |||||
if(!file.isFile()) | |||||
return; | |||||
String packageName = context.getPackageName(); | |||||
Uri apkUri = FileProvider.getUriForFile(context, packageName + ".fileprovider", file); | |||||
Intent intent = new Intent(Intent.ACTION_VIEW); | |||||
intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); | |||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); | |||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |||||
if (!context.getPackageManager().canRequestPackageInstalls()) { | |||||
Toast.makeText(context, "Android 8以上安装apk请求允许未知来源App", Toast.LENGTH_LONG).show(); | |||||
Intent settingsIntent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + packageName)); | |||||
context.startActivity(settingsIntent); | |||||
} else { | |||||
context.startActivity(intent); | |||||
} | |||||
} else { | |||||
context.startActivity(intent); | |||||
} | |||||
} | |||||
public static boolean BuildIsDebug(Context context) | |||||
{ | |||||
try | |||||
{ | |||||
ApplicationInfo info = context.getApplicationInfo(); | |||||
System.err.println(((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) + " -> " + NSConstants.IsDebug()); | |||||
return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 || NSConstants.IsDebug(); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
e.printStackTrace(); | |||||
return NSConstants.IsDebug(); // default is release | |||||
} | |||||
} | |||||
private NSContextUtils() {} | private NSContextUtils() {} | ||||
} | } |
@@ -20,6 +20,7 @@ import androidx.core.app.ActivityCompat; | |||||
import com.nsgk.ruralWeb.FullscreenActivity; | import com.nsgk.ruralWeb.FullscreenActivity; | ||||
import com.nsgk.ruralWeb.R; | import com.nsgk.ruralWeb.R; | ||||
import com.nsgk.ruralWeb.enums.NSEnums; | import com.nsgk.ruralWeb.enums.NSEnums; | ||||
import com.nsgk.ruralWeb.location.NSLastKnownLocation; | |||||
import com.nsgk.ruralWeb.location.NSLocationInfo; | import com.nsgk.ruralWeb.location.NSLocationInfo; | ||||
import com.nsgk.ruralWeb.location.NSAMapLocation; | import com.nsgk.ruralWeb.location.NSAMapLocation; | ||||
import com.nsgk.ruralWeb.location.NSRealtimeLocation; | import com.nsgk.ruralWeb.location.NSRealtimeLocation; | ||||
@@ -31,41 +32,51 @@ import com.nsgk.ruralWeb.utils.NSContextUtils; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.concurrent.atomic.AtomicInteger; | |||||
public class NSEnvWindowObject | public class NSEnvWindowObject | ||||
{ | { | ||||
private static final String ID_TAG = NSEnvWindowObject.class.getName(); | private static final String ID_TAG = NSEnvWindowObject.class.getName(); | ||||
private static final String FUSED_PROVIDER = "fused"; | |||||
private final Handler m_handler; | private final Handler m_handler; | ||||
private final Context m_context; | private final Context m_context; | ||||
private final WebView m_webView; | private final WebView m_webView; | ||||
private final NSSystemLocation location; | |||||
private final NSSystemLocation m_systemLocation; | |||||
private final NSLastKnownLocation m_lastKnownLocation; | |||||
private final NSAMapLocation m_amapLocation; | |||||
private final NSRealtimeLocation m_realtimeLocation; | |||||
private final NSAMapLocation amapLocation; | |||||
private final NSRealtimeLocation realtimeLocation; | |||||
private final NSPreference preference; | |||||
private final NSPreference m_preference; | |||||
// 最近一次获取到的定位坐标, 如果获取定位失败则返回此值. 可能不需要, 因为PASSIVE_PROVIDER就为最近的定位 | // 最近一次获取到的定位坐标, 如果获取定位失败则返回此值. 可能不需要, 因为PASSIVE_PROVIDER就为最近的定位 | ||||
private String lastLocation = null; | |||||
private String m_lastLocation = null; | |||||
private static final int LOCATION_STATE_READY = 0; // 准备 | |||||
private static final int LOCATION_STATE_PROCESSING = 1; // 进行中 | |||||
private static final int LOCATION_STATE_FINISH = 2; // 完成 | |||||
private static final int LOCATION_STATE_TERMINATED = 3; // 中止 | |||||
private AtomicInteger m_locationState = new AtomicInteger(LOCATION_STATE_READY); | |||||
public NSEnvWindowObject(Context context, Handler handler, WebView webView) | public NSEnvWindowObject(Context context, Handler handler, WebView webView) | ||||
{ | { | ||||
m_context = context; | m_context = context; | ||||
m_handler = handler; | m_handler = handler; | ||||
m_webView = webView; | m_webView = webView; | ||||
location = new NSSystemLocation(m_context); | |||||
amapLocation = new NSAMapLocation(m_context); | |||||
realtimeLocation = new NSRealtimeLocation(m_context); | |||||
preference = new NSPreference(m_context); | |||||
m_systemLocation = new NSSystemLocation(m_context); | |||||
m_lastKnownLocation = new NSLastKnownLocation(m_context); | |||||
m_amapLocation = new NSAMapLocation(m_context); | |||||
m_realtimeLocation = new NSRealtimeLocation(m_context); | |||||
m_preference = new NSPreference(m_context); | |||||
} | } | ||||
public void OnDestroy() | public void OnDestroy() | ||||
{ | { | ||||
if(amapLocation.IsInitialized()) | |||||
amapLocation.Shutdown(); | |||||
if(realtimeLocation.IsInitialized()) | |||||
realtimeLocation.Shutdown(); | |||||
if(m_amapLocation.IsInitialized()) | |||||
m_amapLocation.Shutdown(); | |||||
if(m_realtimeLocation.IsInitialized()) | |||||
m_realtimeLocation.Shutdown(); | |||||
m_systemLocation.Shutdown(); | |||||
} | } | ||||
@JavascriptInterface | @JavascriptInterface | ||||
@@ -76,12 +87,8 @@ public class NSEnvWindowObject | |||||
private void ShowToast(final String message, int duration) | private void ShowToast(final String message, int duration) | ||||
{ | { | ||||
RunOnUIThread(new Runnable() { | |||||
@Override | |||||
public void run() | |||||
{ | |||||
Toast.makeText(m_context, message, duration).show(); | |||||
} | |||||
RunOnUIThread(() -> { | |||||
Toast.makeText(m_context, message, duration).show(); | |||||
}); | }); | ||||
} | } | ||||
@@ -98,37 +105,44 @@ public class NSEnvWindowObject | |||||
if(!CheckLocationPermission()) | if(!CheckLocationPermission()) | ||||
{ | { | ||||
return lastLocation; | |||||
return m_lastLocation; | |||||
} | } | ||||
SetLocationState(LOCATION_STATE_READY); | |||||
ShowIndicator(); | |||||
NSLocationInfo loc; | NSLocationInfo loc; | ||||
String location = CurrentLocationMode(); | String location = CurrentLocationMode(); | ||||
String provider = preference.GetString(NSPreference.LOCATION_PROVIDER, NSConstants.DEFAULT_LOCATION_PROVIDER); | |||||
String provider = m_preference.GetString(NSPreference.LOCATION_PROVIDER, NSConstants.DEFAULT_LOCATION_PROVIDER); | |||||
Log.d(ID_TAG, "定位提供器: " + provider); | Log.d(ID_TAG, "定位提供器: " + provider); | ||||
SetLocationState(LOCATION_STATE_PROCESSING); | |||||
switch(location) | switch(location) | ||||
{ | { | ||||
case NSEnums.LocationMode.GAODE: | case NSEnums.LocationMode.GAODE: | ||||
loc = GetAMapLocation(); | loc = GetAMapLocation(); | ||||
if(null == loc) | |||||
loc = GetBuiltInLocation(provider); | |||||
break; | break; | ||||
case NSEnums.LocationMode.REALTIME: | case NSEnums.LocationMode.REALTIME: | ||||
loc = GetRealtimeLocation(); | loc = GetRealtimeLocation(); | ||||
if(null == loc) | |||||
loc = GetBuiltInLocation(provider); | |||||
break; | break; | ||||
case NSEnums.LocationMode.SYSTEM: | case NSEnums.LocationMode.SYSTEM: | ||||
default: | default: | ||||
loc = GetBuiltInLocation(provider); | |||||
loc = GetCurrentLocation(provider); | |||||
break; | break; | ||||
} | } | ||||
SetLocationState(LOCATION_STATE_FINISH, LOCATION_STATE_PROCESSING); | |||||
if(null == loc) | |||||
{ | |||||
if(IsLocationState(LOCATION_STATE_FINISH)) | |||||
ShowToast("定位失败, 请先开启位置服务", Toast.LENGTH_LONG); | |||||
loc = GetLastKnownLocation(provider); | |||||
} | |||||
HideIndicator(); | |||||
return SetLastLocation(loc); | return SetLastLocation(loc); | ||||
} | } | ||||
public String CurrentLocationMode() | public String CurrentLocationMode() | ||||
{ | { | ||||
return preference.GetString(NSPreference.LOCATION_MODE, NSConstants.DEFAULT_LOCATION_MODE); | |||||
return m_preference.GetString(NSPreference.LOCATION_MODE, NSConstants.DEFAULT_LOCATION_MODE); | |||||
} | } | ||||
@JavascriptInterface | @JavascriptInterface | ||||
@@ -140,7 +154,7 @@ public class NSEnvWindowObject | |||||
@JavascriptInterface | @JavascriptInterface | ||||
public int GetLocationTimeout() | public int GetLocationTimeout() | ||||
{ | { | ||||
return preference.GetIntFromString(NSPreference.LOCATION_TIMEOUT, NSConstants.DEFAULT_LOCATION_TIMEOUT); | |||||
return m_preference.GetIntFromString(NSPreference.LOCATION_TIMEOUT, NSConstants.DEFAULT_LOCATION_TIMEOUT); | |||||
} | } | ||||
@JavascriptInterface | @JavascriptInterface | ||||
@@ -182,7 +196,7 @@ public class NSEnvWindowObject | |||||
} | } | ||||
} | } | ||||
preference.SetString(NSPreference.LOCATION_MODE, mode); | |||||
m_preference.SetString(NSPreference.LOCATION_MODE, mode); | |||||
res[0] = mode; | res[0] = mode; | ||||
String name = locationModeList.get(selected[0]); | String name = locationModeList.get(selected[0]); | ||||
Toast.makeText(m_context, "使用" + name + "定位", Toast.LENGTH_SHORT).show(); | Toast.makeText(m_context, "使用" + name + "定位", Toast.LENGTH_SHORT).show(); | ||||
@@ -192,7 +206,7 @@ public class NSEnvWindowObject | |||||
}); | }); | ||||
builder.setNeutralButton("默认", (DialogInterface dialog, int which) -> { | builder.setNeutralButton("默认", (DialogInterface dialog, int which) -> { | ||||
res[0] = NSConstants.DEFAULT_LOCATION_MODE; | res[0] = NSConstants.DEFAULT_LOCATION_MODE; | ||||
preference.SetString(NSPreference.LOCATION_MODE, res[0]); | |||||
m_preference.SetString(NSPreference.LOCATION_MODE, res[0]); | |||||
int choose = locationModeValueList.indexOf(res[0]); | int choose = locationModeValueList.indexOf(res[0]); | ||||
String name = locationModeList.get(choose); | String name = locationModeList.get(choose); | ||||
Toast.makeText(m_context, "使用" + name + "定位", Toast.LENGTH_SHORT).show(); | Toast.makeText(m_context, "使用" + name + "定位", Toast.LENGTH_SHORT).show(); | ||||
@@ -225,20 +239,21 @@ public class NSEnvWindowObject | |||||
private String SetLastLocation(NSLocationInfo loc) | private String SetLastLocation(NSLocationInfo loc) | ||||
{ | { | ||||
if(null != loc) | if(null != loc) | ||||
lastLocation = ReturnLocation(loc); | |||||
return lastLocation; | |||||
m_lastLocation = ReturnLocation(loc); | |||||
return m_lastLocation; | |||||
} | } | ||||
private NSLocationInfo GetBuiltInLocation(String type) | |||||
private NSLocationInfo GetCurrentLocation(String type) | |||||
{ | { | ||||
Log.i(ID_TAG, "使用系统定位"); | |||||
Log.i(ID_TAG, "使用系统当前定位"); | |||||
NSLocationInfo loc = null; | NSLocationInfo loc = null; | ||||
try | try | ||||
{ | { | ||||
int timeout = m_preference.GetIntFromString(NSPreference.LOCATION_TIMEOUT, NSConstants.DEFAULT_LOCATION_TIMEOUT); | |||||
long start = System.currentTimeMillis(); | long start = System.currentTimeMillis(); | ||||
loc = location.GetLocation(type); | |||||
loc = m_systemLocation.Read(type, timeout); | |||||
long end = System.currentTimeMillis(); | long end = System.currentTimeMillis(); | ||||
Log.i(ID_TAG, "系统定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); | |||||
Log.i(ID_TAG, "系统当前定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); | |||||
} | } | ||||
catch(Throwable e) | catch(Throwable e) | ||||
{ | { | ||||
@@ -247,6 +262,24 @@ public class NSEnvWindowObject | |||||
return loc; | return loc; | ||||
} | } | ||||
private NSLocationInfo GetLastKnownLocation(String type) | |||||
{ | |||||
Log.i(ID_TAG, "使用系统最近定位"); | |||||
NSLocationInfo loc; | |||||
try | |||||
{ | |||||
long start = System.currentTimeMillis(); | |||||
loc = m_lastKnownLocation.Read(type); | |||||
long end = System.currentTimeMillis(); | |||||
Log.i(ID_TAG, "系统定位最近结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); | |||||
} | |||||
catch(Throwable e) | |||||
{ | |||||
e.printStackTrace(); | |||||
} | |||||
return m_lastKnownLocation.GetLastLocation(); | |||||
} | |||||
private NSLocationInfo GetRealtimeLocation() | private NSLocationInfo GetRealtimeLocation() | ||||
{ | { | ||||
Log.i(ID_TAG, "使用系统实时定位"); | Log.i(ID_TAG, "使用系统实时定位"); | ||||
@@ -254,10 +287,10 @@ public class NSEnvWindowObject | |||||
try | try | ||||
{ | { | ||||
NSPreference preference = new NSPreference(m_context); | NSPreference preference = new NSPreference(m_context); | ||||
if(!realtimeLocation.IsInitialized()) | |||||
if(!m_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)); | |||||
m_realtimeLocation.SetOption(NSRealtimeLocation.OPTION_MIN_TIME, preference.GetIntFromString(NSPreference.LOCATION_REALTIME_INTERVAL, NSConstants.DEFAULT_LOCATION_REALTIME_INTERVAL)); | |||||
m_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; | int flag = NSRealtimeLocation.DEFAULT_FLAG | NSRealtimeLocation.FLAG_BUILTIN_THREAD; | ||||
String provider = preference.GetString(NSPreference.LOCATION_PROVIDER, NSConstants.DEFAULT_LOCATION_PROVIDER); | String provider = preference.GetString(NSPreference.LOCATION_PROVIDER, NSConstants.DEFAULT_LOCATION_PROVIDER); | ||||
if(LocationManager.GPS_PROVIDER.equals(provider)) | if(LocationManager.GPS_PROVIDER.equals(provider)) | ||||
@@ -265,12 +298,12 @@ public class NSEnvWindowObject | |||||
flag &= ~NSRealtimeLocation.FLAG_PRIORITY_NETWORK; | flag &= ~NSRealtimeLocation.FLAG_PRIORITY_NETWORK; | ||||
flag |= NSRealtimeLocation.FLAG_PRIORITY_GPS; | flag |= NSRealtimeLocation.FLAG_PRIORITY_GPS; | ||||
} | } | ||||
realtimeLocation.Init(flag); | |||||
m_realtimeLocation.Init(flag); | |||||
} | } | ||||
long start = System.currentTimeMillis(); | long start = System.currentTimeMillis(); | ||||
int count = preference.GetIntFromString(NSPreference.LOCATION_REALTIME_READ_COUNT, NSConstants.DEFAULT_LOCATION_REALTIME_READ_COUNT); | int count = preference.GetIntFromString(NSPreference.LOCATION_REALTIME_READ_COUNT, NSConstants.DEFAULT_LOCATION_REALTIME_READ_COUNT); | ||||
int timeout = preference.GetIntFromString(NSPreference.LOCATION_TIMEOUT, NSConstants.DEFAULT_LOCATION_TIMEOUT); | int timeout = preference.GetIntFromString(NSPreference.LOCATION_TIMEOUT, NSConstants.DEFAULT_LOCATION_TIMEOUT); | ||||
loc = realtimeLocation.Read(count, timeout); | |||||
loc = m_realtimeLocation.Read(count, timeout); | |||||
long end = System.currentTimeMillis(); | long end = System.currentTimeMillis(); | ||||
Log.i(ID_TAG, "系统实时定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); | Log.i(ID_TAG, "系统实时定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); | ||||
} | } | ||||
@@ -288,15 +321,15 @@ public class NSEnvWindowObject | |||||
try | try | ||||
{ | { | ||||
NSPreference preference = new NSPreference(m_context); | NSPreference preference = new NSPreference(m_context); | ||||
if(!amapLocation.IsInitialized()) | |||||
if(!m_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); | |||||
m_amapLocation.SetOption(NSAMapLocation.OPTION_INTERVAL, preference.GetIntFromString(NSPreference.LOCATION_GAODE_INTERVAL, NSConstants.DEFAULT_LOCATION_GAODE_INTERVAL)); | |||||
m_amapLocation.Init(NSAMapLocation.DEFAULT_FLAG | NSAMapLocation.FLAG_BUILTIN_THREAD); | |||||
} | } | ||||
long start = System.currentTimeMillis(); | long start = System.currentTimeMillis(); | ||||
int count = preference.GetIntFromString(NSPreference.LOCATION_GAODE_READ_COUNT, NSConstants.DEFAULT_LOCATION_GAODE_READ_COUNT); | int count = preference.GetIntFromString(NSPreference.LOCATION_GAODE_READ_COUNT, NSConstants.DEFAULT_LOCATION_GAODE_READ_COUNT); | ||||
int timeout = preference.GetIntFromString(NSPreference.LOCATION_TIMEOUT, NSConstants.DEFAULT_LOCATION_TIMEOUT); | int timeout = preference.GetIntFromString(NSPreference.LOCATION_TIMEOUT, NSConstants.DEFAULT_LOCATION_TIMEOUT); | ||||
loc = amapLocation.Read(count, timeout); | |||||
loc = m_amapLocation.Read(count, timeout); | |||||
long end = System.currentTimeMillis(); | long end = System.currentTimeMillis(); | ||||
Log.i(ID_TAG, "高德定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); | Log.i(ID_TAG, "高德定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒"); | ||||
} | } | ||||
@@ -351,19 +384,15 @@ public class NSEnvWindowObject | |||||
sb.append(", "); | sb.append(", "); | ||||
} | } | ||||
final String arg = sb.toString(); | 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)); | |||||
} | |||||
}); | |||||
} | |||||
RunOnUIThread(() -> { | |||||
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)); | |||||
} | |||||
}); | |||||
}); | }); | ||||
} | } | ||||
@@ -377,14 +406,63 @@ public class NSEnvWindowObject | |||||
sb.append(", "); | sb.append(", "); | ||||
} | } | ||||
final String arg = sb.toString(); | 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); | |||||
} | |||||
RunOnUIThread(() -> { | |||||
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); | |||||
}); | |||||
} | |||||
protected void ShowIndicator() | |||||
{ | |||||
RunOnUIThread(() -> { | |||||
((FullscreenActivity)(m_context)).SetIndicatorVisible(true); | |||||
}); | }); | ||||
} | } | ||||
protected void HideIndicator() | |||||
{ | |||||
RunOnUIThread(() -> { | |||||
((FullscreenActivity)(m_context)).SetIndicatorVisible(false); | |||||
}); | |||||
} | |||||
public void TerminateLocation() | |||||
{ | |||||
if(!IsLocationState(LOCATION_STATE_PROCESSING)) | |||||
return; | |||||
SetLocationState(LOCATION_STATE_TERMINATED, LOCATION_STATE_PROCESSING); | |||||
String location = CurrentLocationMode(); | |||||
Log.i(ID_TAG, "中止定位: " + location); | |||||
switch(location) | |||||
{ | |||||
case NSEnums.LocationMode.GAODE: | |||||
m_amapLocation.TerminateRead(); | |||||
break; | |||||
case NSEnums.LocationMode.REALTIME: | |||||
m_realtimeLocation.TerminateRead(); | |||||
break; | |||||
case NSEnums.LocationMode.SYSTEM: | |||||
m_systemLocation.TerminateRead(); | |||||
break; | |||||
} | |||||
HideIndicator(); | |||||
} | |||||
private void SetLocationState(int st) | |||||
{ | |||||
m_locationState.set(st); | |||||
} | |||||
private void SetLocationState(int st, int cur) | |||||
{ | |||||
m_locationState.compareAndSet(cur, st); | |||||
} | |||||
private boolean IsLocationState(int st) | |||||
{ | |||||
return m_locationState.get() == st; | |||||
} | |||||
} | } |
@@ -0,0 +1,12 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" > | |||||
<solid android:color="@color/black_overlay" /> | |||||
<padding | |||||
android:bottom="10dp" | |||||
android:left="20dp" | |||||
android:right="20dp" | |||||
android:top="10dp" /> | |||||
<corners android:radius="10dp" /> | |||||
</shape> |
@@ -0,0 +1,24 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:orientation="vertical" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:background="@drawable/indicator_background"> | |||||
<ProgressBar | |||||
android:id="@+id/progress_indicator" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_gravity="center_horizontal" | |||||
android:indeterminate="true" | |||||
/> | |||||
<Button | |||||
android:id="@+id/terminate_button" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_gravity="center_horizontal" | |||||
android:layout_marginTop="2dp" | |||||
android:text="停止" /> | |||||
</LinearLayout> |
@@ -6,14 +6,14 @@ | |||||
<item>系统(实时)</item> | <item>系统(实时)</item> | ||||
<item>系统</item> | <item>系统</item> | ||||
<item>H5</item> | <item>H5</item> | ||||
<!--<item>高德</item>--> | |||||
<item>高德</item> | |||||
</string-array> | </string-array> | ||||
<string-array name="location_mode_values"> | <string-array name="location_mode_values"> | ||||
<item>realtime</item> | <item>realtime</item> | ||||
<item>system</item> | <item>system</item> | ||||
<item>h5</item> | <item>h5</item> | ||||
<!--<item>gaode</item>--> | |||||
<item>gaode</item> | |||||
</string-array> | </string-array> | ||||
<string-array name="location_provider_labels"> | <string-array name="location_provider_labels"> | ||||
@@ -131,6 +131,13 @@ | |||||
android:persistent="false"> | android:persistent="false"> | ||||
</Preference> | </Preference> | ||||
<Preference | |||||
android:key="UPDATE_DOWNLOAD" | |||||
android:summary="下载更新" | |||||
android:title="下载更新" | |||||
android:persistent="false"> | |||||
</Preference> | |||||
<Preference | <Preference | ||||
android:key="VERSION" | android:key="VERSION" | ||||
android:title="版本" | android:title="版本" | ||||
@@ -32,4 +32,8 @@ appIconKey=yhzl | |||||
# [String] App copyright name, it will save to @string/app_copyright. default using @string/copyright | # [String] App copyright name, it will save to @string/app_copyright. default using @string/copyright | ||||
appCopyright= | appCopyright= | ||||
# [String] App vendor name, it will save to @string/app_vendor. default using @string/company | # [String] App vendor name, it will save to @string/app_vendor. default using @string/company | ||||
appVendor= | |||||
appVendor= | |||||
# [String] App update download url, it will save to @string/app_update_url | |||||
appUpdateUrl=http://218.59.175.43:8090/nsgk/qixingguan.apk | |||||
# gaode amap key | |||||
amapKey=490bef43ef0182379aa1a8bacc45d054 |