Add the ability to open somebody`s location on map in OsmAnd

This commit is contained in:
Alex Sytnyk 2018-07-09 18:51:04 +03:00
parent 4e2500578c
commit 90cc7dd8f4
7 changed files with 143 additions and 8 deletions

View file

@ -16,8 +16,10 @@
android:orientation="vertical">
<LinearLayout
android:id="@+id/user_row"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical">
<ImageView

View file

@ -13,6 +13,7 @@
android:background="?attr/card_bg_color">
<LinearLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:layout_marginBottom="@dimen/list_item_bottom_margin"

View file

@ -0,0 +1,79 @@
package net.osmand.telegram.helpers
import android.content.Intent
import android.net.Uri
import android.support.v4.app.FragmentActivity
import net.osmand.telegram.helpers.TelegramUiHelper.ChatItem
import net.osmand.telegram.helpers.TelegramUiHelper.LocationItem
import net.osmand.telegram.ui.MainActivity
import net.osmand.telegram.utils.AndroidUtils
object OsmandHelper {
private const val PREFIX = "osmand.api://"
private const val API_CMD_SHOW_LOCATION = "show_location"
private const val PARAM_LAT = "lat"
private const val PARAM_LON = "lon"
private const val PARAM_AMAP_LAYER_ID = "amap_layer_id"
private const val PARAM_AMAP_POINT_ID = "amap_point_id"
fun showUserOnMap(activity: FragmentActivity?, chatItem: ChatItem) {
if (chatItem.canBeOpenedOnMap()) {
showLocationPointOnMap(
activity,
chatItem.latLon?.latitude,
chatItem.latLon?.longitude,
"${chatItem.title}_${chatItem.userId}"
)
}
}
fun showUserOnMap(activity: FragmentActivity?, locationItem: LocationItem) {
if (locationItem.canBeOpenedOnMap()) {
val userId = locationItem.senderUserId
val id = if (userId != 0) userId.toString() else locationItem.name
showLocationPointOnMap(
activity,
locationItem.latLon?.latitude,
locationItem.latLon?.longitude,
"${locationItem.chatTitle}_$id"
)
}
}
fun showLocationPointOnMap(
activity: FragmentActivity?,
lat: Double?,
lon: Double?,
pointId: String
) {
if (activity == null || lat == null || lon == null) {
return
}
val params = mapOf(
PARAM_LAT to lat.toString(),
PARAM_LON to lon.toString(),
PARAM_AMAP_LAYER_ID to MAP_LAYER_ID,
PARAM_AMAP_POINT_ID to pointId
)
val intent = Intent(Intent.ACTION_VIEW, createUri(API_CMD_SHOW_LOCATION, params))
if (AndroidUtils.isIntentSafe(activity, intent)) {
activity.startActivity(intent)
} else {
MainActivity.OsmandMissingDialogFragment().show(activity.supportFragmentManager, null)
}
}
private fun createUri(command: String, params: Map<String, String>): Uri {
val sb = StringBuilder(PREFIX).append(command)
if (params.isNotEmpty()) {
sb.append("?")
params.forEach { (key, value) -> sb.append("$key=$value&") }
sb.delete(sb.length - 1, sb.length)
}
return Uri.parse(sb.toString())
}
}

View file

@ -12,7 +12,7 @@ import net.osmand.telegram.utils.AndroidUtils
import org.drinkless.td.libcore.telegram.TdApi
import java.io.File
private const val MAP_LAYER_ID = "telegram_layer"
const val MAP_LAYER_ID = "telegram_layer"
class ShowLocationHelper(private val app: TelegramApplication) {

View file

@ -47,6 +47,7 @@ object TelegramUiHelper {
}
val chatType = chat.type
if (chatType is TdApi.ChatTypePrivate && !helper.isBot(chatType.userId)) {
res.userId = chatType.userId
val content = messages.firstOrNull()?.content
if (content is TdApi.MessageLocation) {
res.latLon = LatLon(content.location.latitude, content.location.longitude)
@ -55,18 +56,26 @@ object TelegramUiHelper {
return res
}
fun messageToLocationItem(helper: TelegramHelper, message: TdApi.Message): LocationItem? {
fun messageToLocationItem(
helper: TelegramHelper,
chat: TdApi.Chat,
message: TdApi.Message
): LocationItem? {
val content = message.content
return when (content) {
is MessageOsmAndBotLocation -> botMessageToLocationItem(content)
is TdApi.MessageLocation -> locationMessageToLocationItem(helper, message)
is MessageOsmAndBotLocation -> botMessageToLocationItem(chat, content)
is TdApi.MessageLocation -> locationMessageToLocationItem(helper, chat, message)
else -> null
}
}
private fun botMessageToLocationItem(content: MessageOsmAndBotLocation): LocationItem? {
private fun botMessageToLocationItem(
chat: TdApi.Chat,
content: MessageOsmAndBotLocation
): LocationItem? {
return if (content.isValid()) {
LocationItem().apply {
chatTitle = chat.title
name = content.name
latLon = LatLon(content.lat, content.lon)
placeholderId = R.drawable.ic_group
@ -78,11 +87,13 @@ object TelegramUiHelper {
private fun locationMessageToLocationItem(
helper: TelegramHelper,
chat: TdApi.Chat,
message: TdApi.Message
): LocationItem? {
val user = helper.getUser(message.senderUserId) ?: return null
val content = message.content as TdApi.MessageLocation
return LocationItem().apply {
chatTitle = chat.title
name = "${user.firstName} ${user.lastName}".trim()
if (name.isEmpty()) {
name = user.username
@ -93,6 +104,7 @@ object TelegramUiHelper {
latLon = LatLon(content.location.latitude, content.location.longitude)
photoPath = helper.getUserPhotoPath(user)
placeholderId = R.drawable.ic_group
senderUserId = message.senderUserId
}
}
@ -105,9 +117,15 @@ object TelegramUiHelper {
internal set
var placeholderId: Int = 0
internal set
var userId: Int = 0
internal set
fun canBeOpenedOnMap() = latLon != null && userId != 0
}
class LocationItem {
var chatTitle: String = ""
internal set
var name: String = ""
internal set
var latLon: LatLon? = null
@ -116,5 +134,9 @@ object TelegramUiHelper {
internal set
var placeholderId: Int = 0
internal set
var senderUserId: Int = 0
internal set
fun canBeOpenedOnMap() = latLon != null
}
}

View file

@ -18,6 +18,7 @@ import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.TelegramLocationProvider.TelegramCompassListener
import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener
import net.osmand.telegram.helpers.OsmandHelper
import net.osmand.telegram.helpers.TelegramHelper.*
import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.helpers.TelegramUiHelper.ChatItem
@ -170,7 +171,7 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
telegramHelper.getChat(id)?.also { chat ->
res.add(TelegramUiHelper.chatToChatItem(telegramHelper, chat, messages))
if (needLocationItems(chat.type)) {
res.addAll(convertToLocationItems(messages))
res.addAll(convertToLocationItems(chat, messages))
}
}
}
@ -186,10 +187,15 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
}
}
private fun convertToLocationItems(messages: List<TdApi.Message>): List<LocationItem> {
private fun convertToLocationItems(
chat: TdApi.Chat,
messages: List<TdApi.Message>
): List<LocationItem> {
val res = mutableListOf<LocationItem>()
messages.forEach { message ->
TelegramUiHelper.messageToLocationItem(telegramHelper, message)?.also { res.add(it) }
TelegramUiHelper.messageToLocationItem(telegramHelper, chat, message)?.also {
res.add(it)
}
}
return res
}
@ -231,7 +237,16 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
val nextIsLocation = !lastItem && items[position + 1] is LocationItem
val chatTitle = item.title
val stateTextInd = if (settings.isShowingChatOnMap(chatTitle)) 1 else 0
val canBeOpenedOnMap = item.canBeOpenedOnMap()
holder.userRow?.isEnabled = canBeOpenedOnMap
if (canBeOpenedOnMap) {
holder.userRow?.setOnClickListener {
OsmandHelper.showUserOnMap(activity, item)
}
} else {
holder.userRow?.setOnClickListener(null)
}
TelegramUiHelper.setupPhoto(app, holder.icon, item.photoPath, item.placeholderId)
holder.title?.text = chatTitle
if (location != null && item.latLon != null) {
@ -253,6 +268,16 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
holder.bottomDivider?.visibility = if (nextIsLocation) View.VISIBLE else View.GONE
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
} else if (item is LocationItem && holder is ContactViewHolder) {
val canBeOpenedOnMap = item.canBeOpenedOnMap()
holder.mainView?.isEnabled = canBeOpenedOnMap
if (canBeOpenedOnMap) {
holder.mainView?.setOnClickListener {
OsmandHelper.showUserOnMap(activity, item)
}
} else {
holder.mainView?.setOnClickListener(null)
}
TelegramUiHelper.setupPhoto(app, holder.icon, item.photoPath, item.placeholderId)
holder.title?.text = item.name
if (location != null && item.latLon != null) {
@ -325,6 +350,7 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
}
inner class ContactViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val mainView: View? = view.findViewById(R.id.main_view)
val icon: ImageView? = view.findViewById(R.id.icon)
val title: TextView? = view.findViewById(R.id.title)
val locationViewContainer: View? = view.findViewById(R.id.location_view_container)
@ -335,6 +361,7 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
}
inner class ChatViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val userRow: View? = view.findViewById(R.id.user_row)
val icon: ImageView? = view.findViewById(R.id.icon)
val title: TextView? = view.findViewById(R.id.title)
val locationViewContainer: View? = view.findViewById(R.id.location_view_container)

View file

@ -3,6 +3,7 @@ package net.osmand.telegram.utils
import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.net.Uri
@ -90,4 +91,7 @@ object AndroidUtils {
}
return "https://play.google.com/store/apps/details?id=$packageName"
}
fun isIntentSafe(ctx: Context, intent: Intent) =
ctx.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).isNotEmpty()
}