Merge pull request #7283 from osmandapp/TrackerLiveTrack

Live track updates second part
This commit is contained in:
Alexey 2019-07-17 18:31:57 +03:00 committed by GitHub
commit e66615b32d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 214 additions and 1884 deletions

View file

@ -2,8 +2,6 @@ package net.osmand.util;
import net.osmand.IProgress; import net.osmand.IProgress;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.router.GeneralRouter;
import net.osmand.router.RoutingConfiguration;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
@ -31,7 +29,6 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.Stack;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@ -370,6 +367,14 @@ public class Algorithms {
return ""; return "";
} }
public static void createParentDirsForFile(File file) {
if (file != null && !file.exists()) {
File parent = file.getParentFile();
if (parent != null && !parent.exists()) {
parent.mkdirs();
}
}
}
@SuppressWarnings("TryFinallyCanBeTryWithResources") @SuppressWarnings("TryFinallyCanBeTryWithResources")
public static void fileCopy(File src, File dst) throws IOException { public static void fileCopy(File src, File dst) throws IOException {

View file

@ -21,6 +21,7 @@ import org.drinkless.td.libcore.telegram.TdApi
import java.util.* import java.util.*
private const val UPDATE_LIVE_MESSAGES_INTERVAL_MS = 10000L // 10 sec private const val UPDATE_LIVE_MESSAGES_INTERVAL_MS = 10000L // 10 sec
private const val UPDATE_LIVE_TRACKS_INTERVAL_MS = 30000L // 30 sec
class TelegramService : Service(), LocationListener, TelegramIncomingMessagesListener, class TelegramService : Service(), LocationListener, TelegramIncomingMessagesListener,
TelegramOutgoingMessagesListener { TelegramOutgoingMessagesListener {
@ -32,6 +33,9 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
private var updateShareInfoHandler: Handler? = null private var updateShareInfoHandler: Handler? = null
private var mHandlerThread = HandlerThread("SharingServiceThread") private var mHandlerThread = HandlerThread("SharingServiceThread")
private var updateTracksHandler: Handler? = null
private var tracksHandlerThread = HandlerThread("TracksUpdateServiceThread")
var handler: Handler? = null var handler: Handler? = null
private set private set
var usedBy = 0 var usedBy = 0
@ -53,7 +57,9 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
mHandlerThread.start() mHandlerThread.start()
tracksHandlerThread.start()
updateShareInfoHandler = Handler(mHandlerThread.looper) updateShareInfoHandler = Handler(mHandlerThread.looper)
updateTracksHandler = Handler(tracksHandlerThread.looper)
} }
override fun onBind(intent: Intent): IBinder? { override fun onBind(intent: Intent): IBinder? {
@ -103,6 +109,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
} }
if (isUsedByUsersLocations(usedBy)) { if (isUsedByUsersLocations(usedBy)) {
app.telegramHelper.startLiveMessagesUpdates(app.settings.sendMyLocInterval) app.telegramHelper.startLiveMessagesUpdates(app.settings.sendMyLocInterval)
startTracksUpdates()
} }
val locationNotification = app.notificationHelper.locationNotification val locationNotification = app.notificationHelper.locationNotification
@ -130,6 +137,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
app.telegramHelper.removeOutgoingMessagesListener(this) app.telegramHelper.removeOutgoingMessagesListener(this)
app.settings.save() app.settings.save()
app.telegramService = null app.telegramService = null
tracksHandlerThread.quit()
mHandlerThread.quit() mHandlerThread.quit()
usedBy = 0 usedBy = 0
@ -191,6 +199,17 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
}, UPDATE_LIVE_MESSAGES_INTERVAL_MS) }, UPDATE_LIVE_MESSAGES_INTERVAL_MS)
} }
private fun startTracksUpdates() {
updateTracksHandler?.postDelayed({
if (isUsedByUsersLocations(usedBy)) {
if (app().settings.hasAnyLiveTracksToShowOnMap()) {
app().showLocationHelper.startUpdateTracksTask()
}
startTracksUpdates()
}
}, UPDATE_LIVE_TRACKS_INTERVAL_MS)
}
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
private fun getFirstTimeRunDefaultLocation(): net.osmand.Location? { private fun getFirstTimeRunDefaultLocation(): net.osmand.Location? {
val app = app() val app = app()

View file

@ -164,6 +164,19 @@ class TelegramSettings(private val app: TelegramApplication) {
fun hasAnyChatToShowOnMap() = !hiddenOnMapChats.containsAll(getLiveNowChats()) fun hasAnyChatToShowOnMap() = !hiddenOnMapChats.containsAll(getLiveNowChats())
fun hasAnyLiveTracksToShowOnMap(): Boolean {
val time = System.currentTimeMillis() - locHistoryTime * 1000
val locations = app.locationMessages.getLastLocationMessagesSinceTime(time)
locations.forEach { loc ->
if (liveTracksInfo.any { it.userId == loc.userId && it.chatId == loc.chatId && it.deviceName == loc.deviceName }) {
return true
}
}
return false
}
fun getLiveTracksInfo() = liveTracksInfo
fun isShowingChatOnMap(chatId: Long) = !hiddenOnMapChats.contains(chatId) fun isShowingChatOnMap(chatId: Long) = !hiddenOnMapChats.contains(chatId)
fun isLiveTrackEnabled(userId: Int, chatId: Long, deviceName: String) = fun isLiveTrackEnabled(userId: Int, chatId: Long, deviceName: String) =

View file

@ -79,6 +79,8 @@ class LocationMessages(val app: TelegramApplication) {
fun getLastLocationInfoForUserInChat(userId: Int, chatId: Long, deviceName: String) = fun getLastLocationInfoForUserInChat(userId: Int, chatId: Long, deviceName: String) =
lastLocationPoints.sortedByDescending { it.time }.firstOrNull { it.userId == userId && it.chatId == chatId && it.deviceName == deviceName } lastLocationPoints.sortedByDescending { it.time }.firstOrNull { it.userId == userId && it.chatId == chatId && it.deviceName == deviceName }
fun getLastLocationMessagesSinceTime(time: Long) = lastLocationPoints.filter { it.time > time }
fun addBufferedMessage(message: BufferMessage) { fun addBufferedMessage(message: BufferMessage) {
log.debug("addBufferedMessage $message") log.debug("addBufferedMessage $message")
val messages = mutableListOf(*this.bufferedMessages.toTypedArray()) val messages = mutableListOf(*this.bufferedMessages.toTypedArray())

View file

@ -211,6 +211,25 @@ class OsmandAidlHelper(private val app: TelegramApplication) {
return null return null
} }
/**
* Get list of all imported GPX files.
*
* @return list of imported gpx files.
*/
val importedGpxFiles: List<AGpxFile>?
get() {
if (mIOsmAndAidlInterface != null) {
try {
val files = mutableListOf<AGpxFile>()
mIOsmAndAidlInterface!!.getImportedGpx(files)
return files
} catch (e: RemoteException) {
e.printStackTrace()
}
}
return null
}
init { init {
connectOsmand() connectOsmand()
} }

View file

@ -4,6 +4,9 @@ import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.os.AsyncTask import android.os.AsyncTask
import android.text.TextUtils import android.text.TextUtils
import net.osmand.GPXUtilities
import net.osmand.PlatformUtil
import net.osmand.aidl.gpx.AGpxFile
import net.osmand.aidl.map.ALatLon import net.osmand.aidl.map.ALatLon
import net.osmand.aidl.maplayer.point.AMapPoint import net.osmand.aidl.maplayer.point.AMapPoint
import net.osmand.aidl.mapmarker.AMapMarker import net.osmand.aidl.mapmarker.AMapMarker
@ -24,6 +27,8 @@ import java.util.concurrent.Executors
class ShowLocationHelper(private val app: TelegramApplication) { class ShowLocationHelper(private val app: TelegramApplication) {
private val log = PlatformUtil.getLog(ShowLocationHelper::class.java)
companion object { companion object {
const val MAP_LAYER_ID = "telegram_layer" const val MAP_LAYER_ID = "telegram_layer"
@ -32,11 +37,14 @@ class ShowLocationHelper(private val app: TelegramApplication) {
const val MAP_CONTEXT_MENU_BUTTON_ID = 1 const val MAP_CONTEXT_MENU_BUTTON_ID = 1
const val MAP_CONTEXT_MENU_BUTTONS_PARAMS_ID = "DIRECTION" const val MAP_CONTEXT_MENU_BUTTONS_PARAMS_ID = "DIRECTION"
const val DIRECTION_ICON_ID = "ic_action_start_navigation" const val DIRECTION_ICON_ID = "ic_action_start_navigation"
const val LIVE_TRACKS_DIR = "livetracks"
} }
private val telegramHelper = app.telegramHelper private val telegramHelper = app.telegramHelper
private val osmandAidlHelper = app.osmandAidlHelper private val osmandAidlHelper = app.osmandAidlHelper
private val executor = Executors.newSingleThreadExecutor() private val executor = Executors.newSingleThreadExecutor()
private val liveTracksExecutor = Executors.newSingleThreadExecutor()
private val points = ConcurrentHashMap<String, TdApi.Message>() private val points = ConcurrentHashMap<String, TdApi.Message>()
private val markers = ConcurrentHashMap<String, AMapMarker>() private val markers = ConcurrentHashMap<String, AMapMarker>()
@ -246,6 +254,72 @@ class ShowLocationHelper(private val app: TelegramApplication) {
osmandAidlHelper.removeContextMenuButtons(MAP_CONTEXT_MENU_BUTTONS_PARAMS_ID) osmandAidlHelper.removeContextMenuButtons(MAP_CONTEXT_MENU_BUTTONS_PARAMS_ID)
} }
private fun updateTracksOnMap() {
val startTime = System.currentTimeMillis()
osmandAidlHelper.execOsmandApi {
val gpxFiles = getLiveGpxFiles()
if (gpxFiles.isEmpty()) {
return@execOsmandApi
}
val importedGpxFiles = osmandAidlHelper.importedGpxFiles
gpxFiles.forEach {
if (!isGpxAlreadyImported(importedGpxFiles, it)) {
val listener = object : OsmandLocationUtils.SaveGpxListener {
override fun onSavingGpxFinish(path: String) {
log.debug("LiveTracks onSavingGpxFinish $path time ${startTime - System.currentTimeMillis()}")
val uri = AndroidUtils.getUriForFile(app, File(path))
val destinationPath = "$LIVE_TRACKS_DIR/${it.metadata.name}.gpx"
osmandAidlHelper.importGpxFromUri(uri, destinationPath, GPXUtilities.GPXColor.AQUA.name, true)
log.debug("LiveTracks importGpxFromUri finish time ${startTime - System.currentTimeMillis()}")
}
override fun onSavingGpxError(error: Exception) {
log.error(error)
}
}
OsmandLocationUtils.saveGpx(app, it, listener)
}
}
}
}
private fun isGpxAlreadyImported(importedGpxFiles: List<AGpxFile>?, gpxFile: GPXUtilities.GPXFile): Boolean {
if (importedGpxFiles != null && importedGpxFiles.isNotEmpty()) {
val name = "${gpxFile.metadata.name}.gpx"
val aGpxFile = importedGpxFiles.firstOrNull { it.fileName == name }
if (aGpxFile != null) {
val startTimeImported = aGpxFile.details?.startTime
val endTimeImported = aGpxFile.details?.endTime
if (startTimeImported != null && endTimeImported != null) {
val startTime = gpxFile.findPointToShow()?.time
val endTime = gpxFile.lastPoint?.time
if (aGpxFile.details?.startTime == startTime && endTimeImported == endTime) {
return true
}
}
}
}
return false
}
private fun getLiveGpxFiles(): List<GPXUtilities.GPXFile> {
val currentTime = System.currentTimeMillis()
val start = currentTime - app.settings.locHistoryTime * 1000
val locationMessages = mutableListOf<LocationMessages.LocationMessage>()
app.settings.getLiveTracksInfo().forEach {
val messages = app.locationMessages.getMessagesForUserInChat(it.userId, it.chatId, it.deviceName, start, currentTime)
if (messages.isNotEmpty()) {
locationMessages.addAll(messages)
}
}
return OsmandLocationUtils.convertLocationMessagesToGpxFiles(app, locationMessages)
}
fun startShowingLocation() { fun startShowingLocation() {
if (!showingLocation && !forcedStop) { if (!showingLocation && !forcedStop) {
showingLocation = if (isUseOsmandCallback() && !app.settings.monitoringEnabled) { showingLocation = if (isUseOsmandCallback() && !app.settings.monitoringEnabled) {
@ -317,6 +391,10 @@ class ShowLocationHelper(private val app: TelegramApplication) {
UpdateMessagesTask(app).executeOnExecutor(executor) UpdateMessagesTask(app).executeOnExecutor(executor)
} }
fun startUpdateTracksTask() {
UpdateTracksTask(app).executeOnExecutor(liveTracksExecutor)
}
private class ShowMessagesTask(private val app: TelegramApplication) : AsyncTask<TdApi.Message, Void, Void?>() { private class ShowMessagesTask(private val app: TelegramApplication) : AsyncTask<TdApi.Message, Void, Void?>() {
override fun doInBackground(vararg messages: TdApi.Message): Void? { override fun doInBackground(vararg messages: TdApi.Message): Void? {
@ -345,6 +423,14 @@ class ShowLocationHelper(private val app: TelegramApplication) {
} }
} }
private class UpdateTracksTask(private val app: TelegramApplication) : AsyncTask<Void, Void, Void?>() {
override fun doInBackground(vararg params: Void?): Void? {
app.showLocationHelper.updateTracksOnMap()
return null
}
}
private fun generatePointDetails(bearing: Float?, altitude: Float?, precision: Float?): List<String> { private fun generatePointDetails(bearing: Float?, altitude: Float?, precision: Float?): List<String> {
val details = mutableListOf<String>() val details = mutableListOf<String>()
if (bearing != null && bearing != 0.0f) { if (bearing != null && bearing != 0.0f) {

View file

@ -23,6 +23,7 @@ import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import net.osmand.GPXUtilities
import net.osmand.PlatformUtil import net.osmand.PlatformUtil
import net.osmand.aidl.gpx.AGpxBitmap import net.osmand.aidl.gpx.AGpxBitmap
import net.osmand.telegram.R import net.osmand.telegram.R
@ -30,7 +31,9 @@ import net.osmand.telegram.TelegramSettings
import net.osmand.telegram.helpers.LocationMessages import net.osmand.telegram.helpers.LocationMessages
import net.osmand.telegram.helpers.OsmandAidlHelper import net.osmand.telegram.helpers.OsmandAidlHelper
import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.utils.* import net.osmand.telegram.utils.AndroidUtils
import net.osmand.telegram.utils.OsmandFormatter
import net.osmand.telegram.utils.OsmandLocationUtils
import net.osmand.util.Algorithms import net.osmand.util.Algorithms
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -42,7 +45,7 @@ class UserGpxInfoFragment : BaseDialogFragment() {
private val uiUtils get() = app.uiUtils private val uiUtils get() = app.uiUtils
private var gpxFile = GPXUtilities.GPXFile() private var gpxFile = GPXUtilities.GPXFile("")
private lateinit var mainView: View private lateinit var mainView: View
private lateinit var dateStartBtn: TextView private lateinit var dateStartBtn: TextView
@ -101,8 +104,8 @@ class UserGpxInfoFragment : BaseDialogFragment() {
openGpx(path) openGpx(path)
} }
override fun onSavingGpxError(warnings: List<String>?) { override fun onSavingGpxError(error: Exception) {
Toast.makeText(app, warnings?.firstOrNull(), Toast.LENGTH_LONG).show() Toast.makeText(app, error.message, Toast.LENGTH_LONG).show()
} }
}) })
} }
@ -198,8 +201,8 @@ class UserGpxInfoFragment : BaseDialogFragment() {
(activity as MainActivity).shareGpx(path) (activity as MainActivity).shareGpx(path)
} }
override fun onSavingGpxError(warnings: List<String>?) { override fun onSavingGpxError(error: Exception) {
Toast.makeText(app, warnings?.firstOrNull(), Toast.LENGTH_LONG).show() Toast.makeText(app, error.message, Toast.LENGTH_LONG).show()
} }
}) })
} }
@ -224,6 +227,13 @@ class UserGpxInfoFragment : BaseDialogFragment() {
} }
} }
override fun onResume() {
super.onResume()
if (liveTrackEnabled()) {
startHandler()
}
}
private fun startHandler() { private fun startHandler() {
log.debug("startHandler") log.debug("startHandler")
if (!handler.hasMessages(TRACK_UPDATE_MSG_ID)) { if (!handler.hasMessages(TRACK_UPDATE_MSG_ID)) {
@ -256,10 +266,7 @@ class UserGpxInfoFragment : BaseDialogFragment() {
} }
private fun saveCurrentGpxToFile(listener: OsmandLocationUtils.SaveGpxListener) { private fun saveCurrentGpxToFile(listener: OsmandLocationUtils.SaveGpxListener) {
if (!gpxFile.isEmpty) { OsmandLocationUtils.saveGpx(app, gpxFile, listener)
val file = File(app.getExternalFilesDir(null), TRACKS_DIR)
OsmandLocationUtils.saveGpx(app, listener, file, gpxFile)
}
} }
private fun readFromBundle(bundle: Bundle?) { private fun readFromBundle(bundle: Bundle?) {
@ -320,7 +327,7 @@ class UserGpxInfoFragment : BaseDialogFragment() {
checkTime() checkTime()
locationMessages = app.locationMessages.getMessagesForUserInChat(userId, chatId, deviceName, startCalendar.timeInMillis, endCalendar.timeInMillis) locationMessages = app.locationMessages.getMessagesForUserInChat(userId, chatId, deviceName, startCalendar.timeInMillis, endCalendar.timeInMillis)
gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages).firstOrNull()?:GPXUtilities.GPXFile() gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(app, locationMessages).firstOrNull() ?: GPXUtilities.GPXFile(app.packageName)
updateGPXStatisticRow() updateGPXStatisticRow()
updateDateAndTimeButtons() updateDateAndTimeButtons()
updateGPXMap() updateGPXMap()
@ -390,8 +397,8 @@ class UserGpxInfoFragment : BaseDialogFragment() {
} }
} }
override fun onSavingGpxError(warnings: List<String>?) { override fun onSavingGpxError(error: Exception) {
log.debug("onSavingGpxError ${warnings?.firstOrNull()}") log.error(error)
} }
}) })
} }

File diff suppressed because it is too large Load diff

View file

@ -1,24 +0,0 @@
package net.osmand.telegram.utils;
import android.content.Context;
/**
*/
public interface LocationPoint {
public double getLatitude();
public double getLongitude();
public int getColor();
public boolean isVisible();
// public PointDescription getPointDescription(Context ctx);
// public String getSpeakableName();
//public void prepareCommandPlayer(CommandBuilder cmd, String names);
}

View file

@ -1,6 +1,7 @@
package net.osmand.telegram.utils package net.osmand.telegram.utils
import android.os.AsyncTask import android.os.AsyncTask
import net.osmand.GPXUtilities
import net.osmand.Location import net.osmand.Location
import net.osmand.data.LatLon import net.osmand.data.LatLon
import net.osmand.telegram.TelegramApplication import net.osmand.telegram.TelegramApplication
@ -15,6 +16,7 @@ import org.drinkless.td.libcore.telegram.TdApi
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import kotlin.math.abs
const val TRACKS_DIR = "tracker/" const val TRACKS_DIR = "tracker/"
@ -412,7 +414,7 @@ object OsmandLocationUtils {
return TdApi.InputMessageText(TdApi.FormattedText(textMessage, entities.toTypedArray()), true, true) return TdApi.InputMessageText(TdApi.FormattedText(textMessage, entities.toTypedArray()), true, true)
} }
fun convertLocationMessagesToGpxFiles(items: List<LocationMessage>, newGpxPerChat: Boolean = true): List<GPXUtilities.GPXFile> { fun convertLocationMessagesToGpxFiles(app: TelegramApplication, items: List<LocationMessage>, newGpxPerChat: Boolean = true): List<GPXUtilities.GPXFile> {
val dataTracks = ArrayList<GPXUtilities.GPXFile>() val dataTracks = ArrayList<GPXUtilities.GPXFile>()
var previousTime: Long = -1 var previousTime: Long = -1
@ -432,24 +434,24 @@ object OsmandLocationUtils {
} }
countedLocations++ countedLocations++
if (previousUserId != userId || (newGpxPerChat && previousChatId != chatId)) { if (previousUserId != userId || (newGpxPerChat && previousChatId != chatId)) {
gpx = GPXUtilities.GPXFile() gpx = GPXUtilities.GPXFile(app.packageName).apply {
gpx!!.chatId = chatId metadata = GPXUtilities.Metadata().apply {
gpx!!.userId = userId name = getGpxFileNameForUserId(app, userId, time)
}
}
previousTime = 0 previousTime = 0
track = null track = null
segment = null segment = null
dataTracks.add(gpx!!) dataTracks.add(gpx!!)
} }
val pt = GPXUtilities.WptPt() val pt = GPXUtilities.WptPt()
pt.userId = userId
pt.chatId = chatId
pt.lat = it.lat pt.lat = it.lat
pt.lon = it.lon pt.lon = it.lon
pt.ele = it.altitude pt.ele = it.altitude
pt.speed = it.speed pt.speed = it.speed
pt.hdop = it.hdop pt.hdop = it.hdop
pt.time = time pt.time = time
val currentInterval = Math.abs(time - previousTime) val currentInterval = abs(time - previousTime)
if (track != null) { if (track != null) {
if (currentInterval < 30 * 60 * 1000) { if (currentInterval < 30 * 60 * 1000) {
// 30 minute - same segment // 30 minute - same segment
@ -475,13 +477,27 @@ object OsmandLocationUtils {
return dataTracks return dataTracks
} }
fun saveGpx(app: TelegramApplication, listener: SaveGpxListener, dir: File, gpxFile: GPXUtilities.GPXFile) { fun saveGpx(app: TelegramApplication, gpxFile: GPXUtilities.GPXFile, listener: SaveGpxListener) {
if (!gpxFile.isEmpty) { if (!gpxFile.isEmpty) {
val task = SaveGPXTrackToFileTask(app, listener, gpxFile, dir, 0) val dir = File(app.getExternalFilesDir(null), TRACKS_DIR)
val task = SaveGPXTrackToFileTask(listener, gpxFile, dir)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
} }
} }
fun getGpxFileNameForUserId(app: TelegramApplication, userId: Int, time: Long): String {
var userName = userId.toString()
try {
val user = app.telegramHelper.getUser(userId)
if (user != null) {
userName = TelegramUiHelper.getUserName(user)
}
} catch (e: NumberFormatException) {
//ignore
}
return "${userName}_${UTC_DATE_FORMAT.format(Date(time))}"
}
abstract class MessageLocation : TdApi.MessageContent() { abstract class MessageLocation : TdApi.MessageContent() {
var lat: Double = Double.NaN var lat: Double = Double.NaN
@ -521,47 +537,34 @@ object OsmandLocationUtils {
} }
private class SaveGPXTrackToFileTask internal constructor( private class SaveGPXTrackToFileTask internal constructor(
private val app: TelegramApplication, private val listener: SaveGpxListener?, private val listener: SaveGpxListener?,
private val gpxFile: GPXUtilities.GPXFile, private val dir: File, private val userId: Int private val gpxFile: GPXUtilities.GPXFile,
private val dir: File
) : ) :
AsyncTask<Void, Void, List<String>>() { AsyncTask<Void, Void, java.lang.Exception>() {
override fun doInBackground(vararg params: Void): List<String> { override fun doInBackground(vararg params: Void): Exception? {
val warnings = ArrayList<String>()
dir.mkdirs() dir.mkdirs()
if (dir.parentFile.canWrite()) { if (dir.parentFile.canWrite()) {
if (dir.exists()) { if (dir.exists()) {
// save file // save file
var fout = File(dir, "$userId.gpx")
if (!gpxFile.isEmpty) { if (!gpxFile.isEmpty) {
val pt = gpxFile.findPointToShow() val fileName = gpxFile.metadata.name
val fout = File(dir, "$fileName.gpx")
val user = app.telegramHelper.getUser(pt!!.userId) return GPXUtilities.writeGpxFile(fout, gpxFile)
val fileName: String
fileName = if (user != null) {
(TelegramUiHelper.getUserName(user) + "_" + SimpleDateFormat("yyyy-MM-dd", Locale.US).format(Date(pt.time)))
} else {
userId.toString() + "_" + SimpleDateFormat("yyyy-MM-dd", Locale.US).format(Date(pt.time))
}
fout = File(dir, "$fileName.gpx")
}
val warn = GPXUtilities.writeGpxFile(fout, gpxFile, app)
if (warn != null) {
warnings.add(warn)
return warnings
} }
} }
} }
return null
}
return warnings override fun onPostExecute(warning: Exception?) {
}
override fun onPostExecute(warnings: List<String>?) {
if (listener != null) { if (listener != null) {
if (warnings != null && warnings.isEmpty()) { if (warning == null) {
listener.onSavingGpxFinish(gpxFile.path) listener.onSavingGpxFinish(gpxFile.path)
} else { } else {
listener.onSavingGpxError(warnings) listener.onSavingGpxError(warning)
} }
} }
} }
@ -571,6 +574,6 @@ object OsmandLocationUtils {
fun onSavingGpxFinish(path: String) fun onSavingGpxFinish(path: String)
fun onSavingGpxError(warnings: List<String>?) fun onSavingGpxError(error: Exception)
} }
} }

View file

@ -74,7 +74,6 @@ import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.dialogs.ConfigureMapMenu; import net.osmand.plus.dialogs.ConfigureMapMenu;
import net.osmand.plus.helpers.ColorDialogs; import net.osmand.plus.helpers.ColorDialogs;
import net.osmand.plus.helpers.ExternalApiHelper; import net.osmand.plus.helpers.ExternalApiHelper;
import net.osmand.plus.helpers.LockHelper;
import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.mapcontextmenu.other.IContextMenuButtonListener; import net.osmand.plus.mapcontextmenu.other.IContextMenuButtonListener;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
@ -1315,6 +1314,9 @@ public class OsmandAidlApi {
File destination = app.getAppPath(IndexConstants.GPX_INDEX_DIR + destinationPath); File destination = app.getAppPath(IndexConstants.GPX_INDEX_DIR + destinationPath);
if (destination.getParentFile().canWrite()) { if (destination.getParentFile().canWrite()) {
boolean destinationExists = destination.exists(); boolean destinationExists = destination.exists();
if (!destinationExists) {
Algorithms.createParentDirsForFile(destination);
}
try { try {
Algorithms.fileCopy(source, destination); Algorithms.fileCopy(source, destination);
finishGpxImport(destinationExists, destination, color, show); finishGpxImport(destinationExists, destination, color, show);
@ -1336,6 +1338,9 @@ public class OsmandAidlApi {
gpxParcelDescriptor = app.getContentResolver().openFileDescriptor(gpxUri, "r"); gpxParcelDescriptor = app.getContentResolver().openFileDescriptor(gpxUri, "r");
if (gpxParcelDescriptor != null) { if (gpxParcelDescriptor != null) {
boolean destinationExists = destination.exists(); boolean destinationExists = destination.exists();
if (!destinationExists) {
Algorithms.createParentDirsForFile(destination);
}
FileDescriptor fileDescriptor = gpxParcelDescriptor.getFileDescriptor(); FileDescriptor fileDescriptor = gpxParcelDescriptor.getFileDescriptor();
InputStream is = new FileInputStream(fileDescriptor); InputStream is = new FileInputStream(fileDescriptor);
FileOutputStream fout = new FileOutputStream(destination); FileOutputStream fout = new FileOutputStream(destination);
@ -1370,6 +1375,9 @@ public class OsmandAidlApi {
InputStream is = new ByteArrayInputStream(sourceRawData.getBytes()); InputStream is = new ByteArrayInputStream(sourceRawData.getBytes());
FileOutputStream fout = new FileOutputStream(destination); FileOutputStream fout = new FileOutputStream(destination);
boolean destinationExists = destination.exists(); boolean destinationExists = destination.exists();
if (!destinationExists) {
Algorithms.createParentDirsForFile(destination);
}
try { try {
Algorithms.streamCopy(is, fout); Algorithms.streamCopy(is, fout);
finishGpxImport(destinationExists, destination, color, show); finishGpxImport(destinationExists, destination, color, show);