Merge pull request #6979 from osmandapp/TrackerBearing
Add bearing to context menu and text messages
This commit is contained in:
commit
4a4c0a44be
7 changed files with 121 additions and 32 deletions
|
@ -15,6 +15,7 @@ public class AMapPoint implements Parcelable {
|
|||
public static final String POINT_SPEED_PARAM = "point_speed_param";
|
||||
public static final String POINT_TYPE_ICON_NAME_PARAM = "point_type_icon_name_param";
|
||||
public static final String POINT_STALE_LOC_PARAM = "point_stale_loc_param";
|
||||
public static final String POINT_BEARING_PARAM = "point_bearing_param";
|
||||
|
||||
private String id;
|
||||
private String shortName;
|
||||
|
|
|
@ -460,13 +460,18 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
if (shareInfo.lastTextSuccessfulSendTime == -1L && shareInfo.lastMapSuccessfulSendTime == -1L
|
||||
&& ((statusChangeTime / 1000 - shareInfo.start) < SHARING_INITIALIZATION_TIME)) {
|
||||
initializing = true
|
||||
} else if (shareInfo.hasSharingError
|
||||
|| (shareInfo.lastSendTextMessageTime - shareInfo.lastTextSuccessfulSendTime > WAITING_TDLIB_TIME)
|
||||
|| (shareInfo.lastSendMapMessageTime - shareInfo.lastMapSuccessfulSendTime > WAITING_TDLIB_TIME)
|
||||
) {
|
||||
sendChatsErrors = true
|
||||
locationTime = Math.max(shareInfo.lastTextSuccessfulSendTime, shareInfo.lastMapSuccessfulSendTime)
|
||||
chatsIds.add(shareInfo.chatId)
|
||||
} else {
|
||||
val textSharingError = shareInfo.lastSendTextMessageTime - shareInfo.lastTextSuccessfulSendTime > WAITING_TDLIB_TIME
|
||||
val mapSharingError = shareInfo.lastSendMapMessageTime - shareInfo.lastMapSuccessfulSendTime > WAITING_TDLIB_TIME
|
||||
if (shareInfo.hasSharingError
|
||||
|| (shareTypeValue == SHARE_TYPE_MAP_AND_TEXT && (textSharingError || mapSharingError))
|
||||
|| textSharingError && (shareTypeValue == SHARE_TYPE_TEXT)
|
||||
|| mapSharingError && (shareTypeValue == SHARE_TYPE_MAP)
|
||||
) {
|
||||
sendChatsErrors = true
|
||||
locationTime = Math.max(shareInfo.lastTextSuccessfulSendTime, shareInfo.lastMapSuccessfulSendTime)
|
||||
chatsIds.add(shareInfo.chatId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,7 +482,7 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
} else if (!initializing) {
|
||||
when {
|
||||
!gpsEnabled -> {
|
||||
locationTime = app.shareLocationHelper.lastLocationUpdateTime
|
||||
locationTime = app.shareLocationHelper.lastLocationUpdateTime / 1000
|
||||
if (locationTime <= 0) {
|
||||
locationTime = getLastSuccessfulSendTime()
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ private const val USER_SET_LIVE_PERIOD_DELAY_MS = 5000 // 5 sec
|
|||
|
||||
private const val UPDATE_LOCATION_ACCURACY = 150 // 150 meters
|
||||
|
||||
private const val SENT_LOCATIONS_INTERVAL_TIME_MS = 4000 // 4 sec
|
||||
|
||||
class ShareLocationHelper(private val app: TelegramApplication) {
|
||||
|
||||
private val log = PlatformUtil.getLog(ShareLocationHelper::class.java)
|
||||
|
@ -30,6 +32,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
|
||||
var lastLocationUpdateTime: Long = 0
|
||||
|
||||
var lastLocationSentTime: Long = 0
|
||||
|
||||
var lastLocation: Location? = null
|
||||
set(value) {
|
||||
if (lastTimeInMillis == 0L) {
|
||||
|
@ -108,12 +112,16 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
|
||||
fun checkAndSendBufferMessagesToChat(chatId: Long) {
|
||||
val shareInfo = app.settings.getChatsShareInfo()[chatId]
|
||||
if (shareInfo != null) {
|
||||
val shareChatsInfo = app.settings.getChatsShareInfo()
|
||||
val shareInfo = shareChatsInfo[chatId]
|
||||
val chatsCounts = shareChatsInfo.size
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (shareInfo != null && currentTime - lastLocationSentTime > chatsCounts * SENT_LOCATIONS_INTERVAL_TIME_MS) {
|
||||
app.locationMessages.getBufferedTextMessagesForChat(chatId).take(MAX_MESSAGES_IN_TDLIB_PER_CHAT).forEach {
|
||||
if (shareInfo.pendingTdLibText < MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
if (it.deviceName.isEmpty()) {
|
||||
if (!shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.editTextLocation(shareInfo, it)
|
||||
app.locationMessages.removeBufferedMessage(it)
|
||||
}
|
||||
|
@ -126,6 +134,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
if (shareInfo.pendingTdLibMap < MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
if (it.deviceName.isEmpty()) {
|
||||
if (!shareInfo.pendingMapMessage && shareInfo.currentMapMessageId != -1L) {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.editMapLocation(shareInfo, it)
|
||||
app.locationMessages.removeBufferedMessage(it)
|
||||
}
|
||||
|
@ -188,6 +197,14 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
val isBot = app.settings.currentSharingMode != userId.toString()
|
||||
val deviceName = if (isBot) app.settings.currentSharingMode else ""
|
||||
var bufferedMessagesFull = false
|
||||
val chatsCounts = chatsShareInfo.size
|
||||
val currentTime = System.currentTimeMillis()
|
||||
|
||||
app.locationMessages.addMyLocationMessage(location)
|
||||
|
||||
if (currentTime - lastLocationSentTime <= chatsCounts * SENT_LOCATIONS_INTERVAL_TIME_MS) {
|
||||
return
|
||||
}
|
||||
|
||||
chatsShareInfo.values.forEach { shareInfo ->
|
||||
if (shareInfo.pendingTdLibText >= MAX_MESSAGES_IN_TDLIB_PER_CHAT || shareInfo.pendingTdLibMap >= MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
|
@ -209,8 +226,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
prepareTextMessage(shareInfo, messageText, isBot)
|
||||
}
|
||||
}
|
||||
checkAndSendBufferMessagesToChat(shareInfo.chatId)
|
||||
}
|
||||
app.locationMessages.addMyLocationMessage(location)
|
||||
if (bufferedMessagesFull) {
|
||||
checkNetworkType()
|
||||
}
|
||||
|
@ -225,6 +242,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
if (isBot) {
|
||||
sendLocationToBot(message, shareInfo, SHARE_TYPE_TEXT)
|
||||
} else {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.sendNewTextLocation(shareInfo, message)
|
||||
}
|
||||
}
|
||||
|
@ -237,6 +255,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
} else {
|
||||
if (shareInfo.pendingTdLibText < MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.editTextLocation(shareInfo, message)
|
||||
} else {
|
||||
app.locationMessages.addBufferedMessage(message)
|
||||
|
@ -258,6 +277,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
app.locationMessages.addBufferedMessage(message)
|
||||
}
|
||||
} else {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.sendNewMapLocation(shareInfo, message)
|
||||
}
|
||||
}
|
||||
|
@ -270,6 +290,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
} else {
|
||||
if (shareInfo.pendingTdLibMap < MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.editMapLocation(shareInfo, message)
|
||||
} else {
|
||||
app.locationMessages.addBufferedMessage(message)
|
||||
|
@ -298,6 +319,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
} else if (shareType == SHARE_TYPE_MAP) {
|
||||
shareInfo.lastSendMapMessageTime = (System.currentTimeMillis() / 1000).toInt()
|
||||
}
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false,
|
||||
object : AndroidNetworkUtils.OnRequestResultListener {
|
||||
override fun onResult(result: String?) {
|
||||
|
|
|
@ -90,6 +90,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
if (item.latLon == null) {
|
||||
return
|
||||
}
|
||||
setupMapLayer()
|
||||
osmandAidlHelper.execOsmandApi {
|
||||
osmandAidlHelper.showMapPoint(
|
||||
MAP_LAYER_ID,
|
||||
|
@ -100,7 +101,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
Color.WHITE,
|
||||
ALatLon(item.latLon!!.latitude, item.latLon!!.longitude),
|
||||
generatePointDetails(item.bearing?.toFloat(), item.altitude?.toFloat(), item.precision?.toFloat()),
|
||||
generatePointParams(if (stale) item.grayscalePhotoPath else item.photoPath, stale, item.speed?.toFloat())
|
||||
generatePointParams(if (stale) item.grayscalePhotoPath else item.photoPath, stale, item.speed?.toFloat(), item.bearing?.toFloat())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -147,8 +148,13 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
}
|
||||
setupMapLayer()
|
||||
val params = generatePointParams(photoPath, stale, if (content is MessageUserLocation) content.speed.toFloat() else null)
|
||||
|
||||
var speed = 0f
|
||||
var bearing = 0f
|
||||
if (content is MessageUserLocation) {
|
||||
speed = content.speed.toFloat()
|
||||
bearing = content.bearing.toFloat()
|
||||
}
|
||||
val params = generatePointParams(photoPath, stale, speed, bearing)
|
||||
val typeName = if (isGroup) chatTitle else OsmandFormatter.getListItemLiveTimeDescr(app, date, app.getString(R.string.last_response) + ": ")
|
||||
if (update) {
|
||||
osmandAidlHelper.updateMapPoint(MAP_LAYER_ID, pointId, name, name, typeName, Color.WHITE, aLatLon, details, params)
|
||||
|
@ -158,7 +164,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
points[pointId] = message
|
||||
} else if (content is MessageOsmAndBotLocation && content.isValid()) {
|
||||
setupMapLayer()
|
||||
val params = generatePointParams(null, stale, content.speed.toFloat())
|
||||
val params = generatePointParams(null, stale, content.speed.toFloat(), content.bearing.toFloat())
|
||||
if (update) {
|
||||
osmandAidlHelper.updateMapPoint(MAP_LAYER_ID, pointId, name, name, chatTitle, Color.WHITE, aLatLon, details, params)
|
||||
} else {
|
||||
|
@ -340,7 +346,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
private fun generatePointDetails(bearing: Float?, altitude: Float?, precision: Float?): List<String> {
|
||||
val details = mutableListOf<String>()
|
||||
if (bearing != null && bearing != 0.0f) {
|
||||
details.add(String.format(Locale.US, "${OsmandLocationUtils.BEARING_PREFIX}%.1f \n", bearing))
|
||||
details.add(String.format(Locale.US, "${OsmandLocationUtils.BEARING_PREFIX}%.1f${OsmandLocationUtils.BEARING_SUFFIX} \n", bearing))
|
||||
}
|
||||
if (altitude != null && altitude != 0.0f) {
|
||||
details.add(String.format(Locale.US, "${OsmandLocationUtils.ALTITUDE_PREFIX}%.1f m\n", altitude))
|
||||
|
@ -352,7 +358,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
return details
|
||||
}
|
||||
|
||||
private fun generatePointParams(photoPath: String?, stale: Boolean, speed: Float?): Map<String, String> {
|
||||
private fun generatePointParams(photoPath: String?, stale: Boolean, speed: Float?, bearing: Float?): Map<String, String> {
|
||||
val photoUri = generatePhotoUri(photoPath, stale)
|
||||
app.grantUriPermission(
|
||||
app.settings.appToConnectPackage,
|
||||
|
@ -366,6 +372,9 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
if (speed != 0.0f) {
|
||||
params[AMapPoint.POINT_SPEED_PARAM] = speed.toString()
|
||||
}
|
||||
if (bearing != 0.0f) {
|
||||
params[AMapPoint.POINT_BEARING_PARAM] = bearing.toString()
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ object OsmandLocationUtils {
|
|||
const val BEARING_PREFIX = "Bearing: "
|
||||
const val SPEED_PREFIX = "Speed: "
|
||||
const val HDOP_PREFIX = "Horizontal precision: "
|
||||
const val BEARING_SUFFIX = "°"
|
||||
|
||||
const val NOW = "now"
|
||||
const val FEW_SECONDS_AGO = "few seconds ago"
|
||||
|
@ -241,19 +242,28 @@ object OsmandLocationUtils {
|
|||
}
|
||||
}
|
||||
s.startsWith(SPEED_PREFIX) -> {
|
||||
val altStr = s.removePrefix(SPEED_PREFIX)
|
||||
val speedStr = s.removePrefix(SPEED_PREFIX)
|
||||
try {
|
||||
val alt = altStr.split(" ").first()
|
||||
res.speed = alt.toDouble()
|
||||
val speed = speedStr.split(" ").first()
|
||||
res.speed = speed.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
s.startsWith(BEARING_PREFIX) -> {
|
||||
val bearingStr = s.removePrefix(BEARING_PREFIX)
|
||||
try {
|
||||
val bearing = bearingStr.removeSuffix(BEARING_SUFFIX)
|
||||
res.bearing = bearing.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
s.startsWith(HDOP_PREFIX) -> {
|
||||
val altStr = s.removePrefix(HDOP_PREFIX)
|
||||
val hdopStr = s.removePrefix(HDOP_PREFIX)
|
||||
try {
|
||||
val alt = altStr.split(" ").first()
|
||||
res.hdop = alt.toDouble()
|
||||
val hdop = hdopStr.split(" ").first()
|
||||
res.hdop = hdop.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
@ -336,6 +346,10 @@ object OsmandLocationUtils {
|
|||
entities.add(TdApi.TextEntity(builder.lastIndex, SPEED_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$SPEED_PREFIX%.1f m/s\n", location.speed))
|
||||
}
|
||||
if (location.bearing > 0) {
|
||||
entities.add(TdApi.TextEntity(builder.lastIndex, BEARING_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$BEARING_PREFIX%.1f$BEARING_SUFFIX\n", location.bearing))
|
||||
}
|
||||
if (location.hdop != 0.0 && location.speed == 0.0) {
|
||||
entities.add(TdApi.TextEntity(builder.lastIndex, HDOP_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt()))
|
||||
|
@ -375,6 +389,10 @@ object OsmandLocationUtils {
|
|||
entities.add(TdApi.TextEntity(builder.lastIndex, SPEED_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$SPEED_PREFIX%.1f m/s\n", location.speed))
|
||||
}
|
||||
if (location.bearing > 0) {
|
||||
entities.add(TdApi.TextEntity(builder.lastIndex, BEARING_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$BEARING_PREFIX%.1f$BEARING_SUFFIX\n", location.bearing))
|
||||
}
|
||||
if (location.hdop != 0.0 && location.speed == 0.0) {
|
||||
entities.add(TdApi.TextEntity(builder.lastIndex, HDOP_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt()))
|
||||
|
|
|
@ -15,6 +15,7 @@ public class AMapPoint implements Parcelable {
|
|||
public static final String POINT_SPEED_PARAM = "point_speed_param";
|
||||
public static final String POINT_TYPE_ICON_NAME_PARAM = "point_type_icon_name_param";
|
||||
public static final String POINT_STALE_LOC_PARAM = "point_stale_loc_param";
|
||||
public static final String POINT_BEARING_PARAM = "point_bearing_param";
|
||||
|
||||
private String id;
|
||||
private String shortName;
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.Map;
|
|||
|
||||
public class AMapPointMenuController extends MenuController {
|
||||
|
||||
private static final float NO_SPEED = -1;
|
||||
private static final float NO_VALUE = -1;
|
||||
private static final int NO_ICON = 0;
|
||||
|
||||
private AMapPoint point;
|
||||
|
@ -136,19 +136,40 @@ public class AMapPointMenuController extends MenuController {
|
|||
public CharSequence getAdditionalInfoStr() {
|
||||
MapActivity activity = getMapActivity();
|
||||
if (activity != null) {
|
||||
float speed = getPointSpeed();
|
||||
if (speed != NO_SPEED) {
|
||||
String formatted = OsmAndFormatter.getFormattedSpeed(speed, activity.getMyApplication());
|
||||
return activity.getString(R.string.map_widget_speed) + ": " + formatted;
|
||||
float bearing = getPointBearing();
|
||||
if (bearing != NO_VALUE) {
|
||||
return OsmAndFormatter.getFormattedAzimuth(bearing, activity.getMyApplication());
|
||||
}
|
||||
}
|
||||
return super.getAdditionalInfoStr();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getSubtypeStr() {
|
||||
MapActivity activity = getMapActivity();
|
||||
if (activity != null) {
|
||||
float speed = getPointSpeed();
|
||||
if (speed != NO_VALUE) {
|
||||
return OsmAndFormatter.getFormattedSpeed(speed, activity.getMyApplication());
|
||||
}
|
||||
}
|
||||
return super.getSubtypeStr();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Drawable getSubtypeIcon() {
|
||||
if (getPointSpeed() != NO_VALUE) {
|
||||
return getIcon(R.drawable.ic_action_speed_16);
|
||||
}
|
||||
return super.getSubtypeIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAdditionalInfoIconRes() {
|
||||
if (getPointSpeed() != NO_SPEED) {
|
||||
return R.drawable.ic_action_speed_16;
|
||||
if (getPointBearing() != NO_VALUE) {
|
||||
return R.drawable.ic_action_bearing;
|
||||
}
|
||||
return super.getAdditionalInfoIconRes();
|
||||
}
|
||||
|
@ -214,10 +235,22 @@ public class AMapPointMenuController extends MenuController {
|
|||
try {
|
||||
return Float.parseFloat(speed);
|
||||
} catch (NumberFormatException e) {
|
||||
return NO_SPEED;
|
||||
return NO_VALUE;
|
||||
}
|
||||
}
|
||||
return NO_SPEED;
|
||||
return NO_VALUE;
|
||||
}
|
||||
|
||||
private float getPointBearing() {
|
||||
String bearing = point.getParams().get(AMapPoint.POINT_BEARING_PARAM);
|
||||
if (!TextUtils.isEmpty(bearing)) {
|
||||
try {
|
||||
return Float.parseFloat(bearing);
|
||||
} catch (NumberFormatException e) {
|
||||
return NO_VALUE;
|
||||
}
|
||||
}
|
||||
return NO_VALUE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
Loading…
Reference in a new issue