diff --git a/app/src/main/ic_launcher-114x114.png b/app/src/main/ic_launcher-114x114.png
new file mode 100644
index 000000000..f4ac1da36
Binary files /dev/null and b/app/src/main/ic_launcher-114x114.png differ
diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt
index a2d36be98..dbc81456b 100644
--- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt
+++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt
@@ -334,26 +334,20 @@ class MainActivity : AppCompatActivity(), Logging,
private fun askToRate() {
exceptionReporter { // Got one IllegalArgumentException from inside this lib, but we don't want to crash our app because of bugs in this optional feature
- AppRate.with(this)
+ val hasGooglePlay = GoogleApiAvailability.getInstance()
+ .isGooglePlayServicesAvailable(this) != ConnectionResult.SERVICE_MISSING
+
+ val rater = AppRate.with(this)
.setInstallDays(10.toByte()) // default is 10, 0 means install day, 10 means app is launched 10 or more days later than installation
.setLaunchTimes(10.toByte()) // default is 10, 3 means app is launched 3 or more times
.setRemindInterval(1.toByte()) // default is 1, 1 means app is launched 1 or more days after neutral button clicked
.setRemindLaunchesNumber(1.toByte()) // default is 0, 1 means app is launched 1 or more times after neutral button clicked
- .monitor() // Monitors the app launch times
+ .setStoreType(if (hasGooglePlay) StoreType.GOOGLEPLAY else StoreType.AMAZON)
+
+ rater.monitor() // Monitors the app launch times
// Only ask to rate if the user has a suitable store
- if (AppRate.with(this).storeType == StoreType.GOOGLEPLAY) { // Checks that current app store type from library options is StoreType.GOOGLEPLAY
- if (GoogleApiAvailability.getInstance()
- .isGooglePlayServicesAvailable(this) != ConnectionResult.SERVICE_MISSING
- ) { // Checks that Google Play is available
- AppRate.showRateDialogIfMeetsConditions(this) // Shows the Rate Dialog when conditions are met
-
- // Force the dialog - for testing
- // AppRate.with(this).showRateDialog(this)
- }
- } else {
- AppRate.showRateDialogIfMeetsConditions(this); // Shows the Rate Dialog when conditions are met
- }
+ AppRate.showRateDialogIfMeetsConditions(this); // Shows the Rate Dialog when conditions are met
}
}
diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
index ed94684bb..819f9b592 100644
--- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
+++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
@@ -22,6 +22,7 @@ import com.geeksville.analytics.DataPair
import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
import com.geeksville.android.ServiceClient
+import com.geeksville.android.isGooglePlayAvailable
import com.geeksville.concurrent.handledLaunch
import com.geeksville.mesh.*
import com.geeksville.mesh.MeshProtos.MeshPacket
@@ -242,7 +243,8 @@ class MeshService : Service(), Logging {
@SuppressLint("MissingPermission")
@UiThread
private fun startLocationRequests() {
- if (fusedLocationClient == null) {
+ // FIXME - currently we don't support location reading without google play
+ if (fusedLocationClient == null && isGooglePlayAvailable(this)) {
GeeksvilleApplication.analytics.track("location_start") // Figure out how many users needed to use the phone GPS
val request = LocationRequest.create().apply {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt
index e5c158f85..c96cd66a3 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt
@@ -30,6 +30,7 @@ import androidx.lifecycle.Observer
import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
import com.geeksville.android.hideKeyboard
+import com.geeksville.android.isGooglePlayAvailable
import com.geeksville.concurrent.handledLaunch
import com.geeksville.mesh.MainActivity
import com.geeksville.mesh.R
@@ -687,8 +688,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
// To skip filtering based on name and supported feature flags (UUIDs),
// don't include calls to setNamePattern() and addServiceUuid(),
// respectively. This example uses Bluetooth.
+ // We only look for Mesh (rather than the full name) because NRF52 uses a very short name
val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()
- .setNamePattern(Pattern.compile("Meshtastic_.*"))
+ .setNamePattern(Pattern.compile("Mesh.*"))
// .addServiceUuid(ParcelUuid(RadioInterfaceService.BTM_SERVICE_UUID), null)
.build()
@@ -768,45 +770,48 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
* If the user has not turned on location access throw up a toast warning
*/
private fun checkLocationEnabled() {
- // We do this painful process because LocationManager.isEnabled is only SDK28 or latet
- val builder = LocationSettingsRequest.Builder()
- builder.setNeedBle(true)
+ // If they don't have google play FIXME for now we don't check for location access
+ if (isGooglePlayAvailable(requireContext())) {
+ // We do this painful process because LocationManager.isEnabled is only SDK28 or latet
+ val builder = LocationSettingsRequest.Builder()
+ builder.setNeedBle(true)
- val request = LocationRequest.create().apply {
- priority = LocationRequest.PRIORITY_HIGH_ACCURACY
- }
- builder.addLocationRequest(request) // Make sure we are granted high accuracy permission
+ val request = LocationRequest.create().apply {
+ priority = LocationRequest.PRIORITY_HIGH_ACCURACY
+ }
+ builder.addLocationRequest(request) // Make sure we are granted high accuracy permission
- val locationSettingsResponse = LocationServices.getSettingsClient(requireActivity())
- .checkLocationSettings(builder.build())
+ val locationSettingsResponse = LocationServices.getSettingsClient(requireActivity())
+ .checkLocationSettings(builder.build())
- locationSettingsResponse.addOnSuccessListener {
- debug("We have location access")
- }
+ locationSettingsResponse.addOnSuccessListener {
+ debug("We have location access")
+ }
- locationSettingsResponse.addOnFailureListener { exception ->
- errormsg("Failed to get location access")
- // We always show the toast regardless of what type of exception we receive. Because even non
- // resolvable api exceptions mean user still needs to fix something.
-
- ///if (exception is ResolvableApiException) {
+ locationSettingsResponse.addOnFailureListener { exception ->
+ errormsg("Failed to get location access")
+ // We always show the toast regardless of what type of exception we receive. Because even non
+ // resolvable api exceptions mean user still needs to fix something.
- // Location settings are not satisfied, but this can be fixed
- // by showing the user a dialog.
+ ///if (exception is ResolvableApiException) {
- // Show the dialog by calling startResolutionForResult(),
- // and check the result in onActivityResult().
- // exception.startResolutionForResult(this@MainActivity, REQUEST_CHECK_SETTINGS)
+ // Location settings are not satisfied, but this can be fixed
+ // by showing the user a dialog.
- // For now just punt and show a dialog
- Toast.makeText(
- requireContext(),
- getString(R.string.location_disabled_warning),
- Toast.LENGTH_SHORT
- ).show()
+ // Show the dialog by calling startResolutionForResult(),
+ // and check the result in onActivityResult().
+ // exception.startResolutionForResult(this@MainActivity, REQUEST_CHECK_SETTINGS)
- //} else
- // Exceptions.report(exception)
+ // For now just punt and show a dialog
+ Toast.makeText(
+ requireContext(),
+ getString(R.string.location_disabled_warning),
+ Toast.LENGTH_SHORT
+ ).show()
+
+ //} else
+ // Exceptions.report(exception)
+ }
}
}
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 324354353..cd8c689a2 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -3,40 +3,40 @@
Mesh网络
设置
频道名称
- 频道选项
+ 频道设置
分享
QR码
未设置
连接状态
应用图标
- 未知用户名
+ 未知用户
用户头像
在吗?我找到了快递,它就在一只大老虎旁边,我好害怕😨!
在此发送信息
- Mesh设备未与此手机配对,请配对设备并设置好您的用户名.\n\n此开源应用程序正在进行alpha测试,如果您发现问题,请在我们的网站中发布.\n\n更多信息,请访问此网页 - www.meshtastic.org.
+ 设备未配对,请配对设备并设置好用户名.\n\n此开源应用为测试版,若您发现任何问题可以在下面的网站中发布.\n\n更多信息,请访问此网页 - www.meshtastic.org.
用户名未设置
用户名
- 匿名使用情况统计信息和崩溃报告.
+ 匿名上传崩溃报告.
Mesh设备扫描中...
+ Meshtastic_ac23
+ Meshtastic_1267
此应用程序需要蓝牙权限.请在Android设置中授予权限.
- 错误:此应用需要蓝牙
+ 未开启蓝牙
开始配对
配对失败
用于连接Mesh网络的URL
接受
取消
修改频道
- 您确定要修改通信频道吗?这将会使你与其他节点断开通信.
+ 您确定要修改通信频道?这将会使你与其他节点断开通信.
收到新的频道URL
您是否要切换到\'%s\'频道?
- 您已禁用了分析功能,但是我们的地图提供商(mapbox)要求对其进行分析\'free\' 因此,这将会关闭地图视图.\n\n
- 如果您想看地图, 你将\'需要在设置中打开分析功能(此外,暂时可能需要强制重新启动应用)\n\n
- 如果您想切换到其他地图提供商,请在meshtastic.discourse.group中发布
+ 您已禁用了分析功能,但是我们的地图提供商(mapbox)要求对其进行分析\'free\' 因此,这将会关闭地图视图.\n\n如果您想看地图, 你将\'需要在“设置”中打开匿名统计(同时你需要重启应用)\n\n如果您想切换到其他地图类形,请在meshtastic.discourse.group中发布
缺少必需的权限,Mesh网络将无法正常工作,请在应用程序设置中启用.
- LoRa模块正处于休眠之中,您暂时无法更改频道
+ 模块正处于休眠之中,无法更改频道
反馈BUG
反馈一个BUG
- 您确定要报告错误吗?报告后,请发布在meshtastic.discourse.group中,以便我们将您的报告与您找到的内容进行匹配.
+ 您确定要报告错误吗?报告后,请发布在网站中,以便将您的报告与您找到的内容进行匹配.
报告
选择LoRa模块
您目前已与LoRa模块配对%s
@@ -45,5 +45,27 @@
请在Android设置中配对设备.
配对成功,服务以启动
配对失败,请再次选择
- 位置访问已禁用,将无法为Mesh设备提供位置.
+ 位置访问已被禁用,这将无法为设备提供位置服务.
+ 分享
+ 已断开连接
+ 设备休眠中
+ 连接状态:%s到%s设备在线
+ 节点列表
+ 更新设备固件
+ 已连接设备
+ 手机已连接到 (%s)
+ 未连接,请选择设备
+ 已连接,设备休眠中
+ 更新到%s
+ 应用程序版本过旧
+ 您需要在Google Play商店(或Github)上更新此应用程序,现在您无法与这台Mesh设备通信.
+ 无选择(默认)
+ 短距离(传输快速)
+ 中等范围(传输较快)
+ 较大范围(传输较慢)
+ 超长距离(传输缓慢)
+ 无法识别
+ Mesh服务通知
+ 您需要在设置中启用位置服务
+ 关于
\ No newline at end of file
diff --git a/geeksville-androidlib b/geeksville-androidlib
index ab381a83f..cfe31d66e 160000
--- a/geeksville-androidlib
+++ b/geeksville-androidlib
@@ -1 +1 @@
-Subproject commit ab381a83f5380358fa8412a58635e390c3729192
+Subproject commit cfe31d66e4de324fa91a2978a76ffcfba5e01085
diff --git a/images/amazon-badge.png b/images/amazon-badge.png
new file mode 100644
index 000000000..6ec998b8e
Binary files /dev/null and b/images/amazon-badge.png differ