Merge branch 'master' into RoutePreparationMenu
17
AUTHORS
|
@ -1,17 +0,0 @@
|
|||
Copyright © OsmAnd 2010–2014
|
||||
### Credits to all major contributors/developers:
|
||||
* Victor Shcherb – all parts of the project, originator
|
||||
* Pavol Zibrita – first contributor and developer of some utilities
|
||||
* Dusan Kazik – one of the first contributors
|
||||
* Andre Van Atten – project supporter, active forum participant, one of the first users.
|
||||
* Dr. Hardy Mueller – map appearance concept and base renderers, international consistency and testing, usability, app scoping, concepts, documentation, wiki, market research.
|
||||
* Yvecai – main contributor to Contour Lines and Hillshade maps
|
||||
* Alexey Pelykh – C++ developer, created native library and made application much snappier.
|
||||
* Max (Zahnstocher) – Java contributor, active forum participant.
|
||||
* Harry van der Wolf – contributor to country boundaries, configuration files, address files, and much else; active forum participant.
|
||||
* Robin ‘ypid’ Schneider – opening hours contributor
|
||||
|
||||
### Other Pull requests
|
||||
Copyright © All authors of translations and pull requests could be found in commits history:
|
||||
- Translations are under special “contributor” name ‘weblate’
|
||||
- Pull requests have two committers, first is original contributor and second is project maintainer
|
7
AUTHORS.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
### Credits to all major contributors/developers:
|
||||
Major contributors /developers listed here https://github.com/osmandapp/osmandapp.github.io/blob/master/website/help/about.html#L8
|
||||
|
||||
### Other Pull requests
|
||||
Copyright © All authors of translations and pull requests could be found in commits history:
|
||||
- Translations are under special “contributor” name ‘weblate’
|
||||
- Pull requests have two committers, first is original contributor and second is project maintainer
|
|
@ -554,13 +554,15 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<TransportStop> searchTransportIndex(SearchRequest<TransportStop> req) throws IOException {
|
||||
for (TransportIndex index : transportIndexes) {
|
||||
if (index.stopsFileLength == 0 || index.right < req.left || index.left > req.right || index.top > req.bottom
|
||||
|| index.bottom < req.top) {
|
||||
continue;
|
||||
}
|
||||
if (req.stringTable != null) {
|
||||
req.stringTable.clear();
|
||||
}
|
||||
codedIS.seek(index.stopsFileOffset);
|
||||
int oldLimit = codedIS.pushLimit(index.stopsFileLength);
|
||||
int offset = req.searchResults.size();
|
||||
|
@ -875,6 +877,8 @@ public class BinaryMapIndexReader {
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// lazy initializing trees
|
||||
if (index.trees == null) {
|
||||
index.trees = new ArrayList<MapTree>();
|
||||
|
@ -2074,14 +2078,14 @@ public class BinaryMapIndexReader {
|
|||
private static boolean testAddressSearch = false;
|
||||
private static boolean testAddressSearchName = false;
|
||||
private static boolean testAddressJustifySearch = false;
|
||||
private static boolean testPoiSearch = true;
|
||||
private static boolean testPoiSearch = false;
|
||||
private static boolean testPoiSearchOnPath = false;
|
||||
private static boolean testTransportSearch = true;
|
||||
|
||||
private static int sleft = MapUtils.get31TileNumberX(4.7495);
|
||||
private static int sright = MapUtils.get31TileNumberX(4.8608);
|
||||
private static int stop = MapUtils.get31TileNumberY(52.3395);
|
||||
private static int sbottom = MapUtils.get31TileNumberY(52.2589);
|
||||
private static int sleft = MapUtils.get31TileNumberX(27.55079);
|
||||
private static int sright = MapUtils.get31TileNumberX(27.55317);
|
||||
private static int stop = MapUtils.get31TileNumberY(53.89378);
|
||||
private static int sbottom = MapUtils.get31TileNumberY(53.89276);
|
||||
private static int szoom = 15;
|
||||
|
||||
private static void println(String s) {
|
||||
|
@ -2090,7 +2094,7 @@ public class BinaryMapIndexReader {
|
|||
|
||||
public static void main(String[] args) throws IOException {
|
||||
File fl = new File(System.getProperty("maps") + "/Synthetic_test_rendering.obf");
|
||||
fl = new File(System.getProperty("maps") + "/Map.obf");
|
||||
fl = new File(System.getProperty("maps") + "/Belarus_europe_2.obf");
|
||||
|
||||
RandomAccessFile raf = new RandomAccessFile(fl, "r");
|
||||
|
||||
|
@ -2280,6 +2284,9 @@ public class BinaryMapIndexReader {
|
|||
println(" " + route.getRef() + " " + route.getName() + " " + route.getDistance() + " "
|
||||
+ route.getAvgBothDistance());
|
||||
StringBuilder b = new StringBuilder();
|
||||
if(route.getForwardWays() == null) {
|
||||
continue;
|
||||
}
|
||||
for(Way w : route.getForwardWays()) {
|
||||
b.append(w.getNodes()).append(" ");
|
||||
}
|
||||
|
|
|
@ -5,17 +5,20 @@ import gnu.trove.map.hash.TIntObjectHashMap;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
import net.osmand.binary.OsmandOdb.TransportRouteSchedule;
|
||||
import net.osmand.data.TransportSchedule;
|
||||
import net.osmand.data.TransportStop;
|
||||
import net.osmand.data.TransportStopExit;
|
||||
import net.osmand.osm.edit.Node;
|
||||
import net.osmand.osm.edit.Way;
|
||||
import net.osmand.util.MapUtils;
|
||||
import net.sf.junidecode.Junidecode;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.CodedInputStream;
|
||||
import com.google.protobuf.WireFormat;
|
||||
|
||||
|
@ -239,6 +242,11 @@ public class BinaryMapTransportReaderAdapter {
|
|||
return ((char) i)+"";
|
||||
}
|
||||
|
||||
private String regStr(TIntObjectHashMap<String> stringTable, int i) throws IOException{
|
||||
stringTable.putIfAbsent(i, "");
|
||||
return ((char) i)+"";
|
||||
}
|
||||
|
||||
public net.osmand.data.TransportRoute getTransportRoute(int filePointer, TIntObjectHashMap<String> stringTable,
|
||||
boolean onlyDescription) throws IOException {
|
||||
codedIS.seek(filePointer);
|
||||
|
@ -394,12 +402,12 @@ public class BinaryMapTransportReaderAdapter {
|
|||
int oldLimit = codedIS.pushLimit(ind.stringTable.length);
|
||||
int current = 0;
|
||||
int i = 0;
|
||||
while (i < values.length) {
|
||||
while (i < values.length && codedIS.getBytesUntilLimit() > 0) {
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
break;
|
||||
return;
|
||||
case OsmandOdb.StringTable.S_FIELD_NUMBER:
|
||||
if (current == values[i]) {
|
||||
String value = codedIS.readString();
|
||||
|
@ -446,12 +454,26 @@ public class BinaryMapTransportReaderAdapter {
|
|||
}
|
||||
|
||||
protected void initializeNames(TIntObjectHashMap<String> stringTable, TransportStop s) {
|
||||
for (TransportStopExit exit : s.getExits()) {
|
||||
if (exit.getRef().length() > 0) {
|
||||
exit.setRef(stringTable.get(exit.getRef().charAt(0)));
|
||||
}
|
||||
}
|
||||
if (s.getName().length() > 0) {
|
||||
s.setName(stringTable.get(s.getName().charAt(0)));
|
||||
}
|
||||
if (s.getEnName(false).length() > 0) {
|
||||
s.setEnName(stringTable.get(s.getEnName(false).charAt(0)));
|
||||
}
|
||||
Map<String, String> namesMap = new HashMap<>(s.getNamesMap(false));
|
||||
if (!s.getNamesMap(false).isEmpty()) {
|
||||
s.getNamesMap(false).clear();
|
||||
}
|
||||
Iterator<Map.Entry<String, String>> it = namesMap.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, String> e = it.next();
|
||||
s.setName(stringTable.get(e.getKey().charAt(0)), stringTable.get(e.getValue().charAt(0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -517,6 +539,7 @@ public class BinaryMapTransportReaderAdapter {
|
|||
TransportStop dataObject = new TransportStop();
|
||||
dataObject.setLocation(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, x, y);
|
||||
dataObject.setFileOffset(shift);
|
||||
List<String> names = null;
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
tag = WireFormat.getTagFieldNumber(t);
|
||||
|
@ -543,11 +566,31 @@ public class BinaryMapTransportReaderAdapter {
|
|||
} else {
|
||||
skipUnknownField(t);
|
||||
}
|
||||
|
||||
break;
|
||||
case OsmandOdb.TransportStop.ADDITIONALNAMEPAIRS_FIELD_NUMBER :
|
||||
if (req.stringTable != null) {
|
||||
int sizeL = codedIS.readRawVarint32();
|
||||
int oldRef = codedIS.pushLimit(sizeL);
|
||||
while (codedIS.getBytesUntilLimit() > 0) {
|
||||
dataObject.setName(regStr(req.stringTable,codedIS.readRawVarint32()),
|
||||
regStr(req.stringTable,codedIS.readRawVarint32()));
|
||||
}
|
||||
codedIS.popLimit(oldRef);
|
||||
} else {
|
||||
skipUnknownField(t);
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.TransportStop.ID_FIELD_NUMBER :
|
||||
dataObject.setId(codedIS.readSInt64());
|
||||
break;
|
||||
case OsmandOdb.TransportStop.EXITS_FIELD_NUMBER :
|
||||
int length = codedIS.readRawVarint32();
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
|
||||
TransportStopExit transportStopExit = readTransportStopExit(cleft, ctop, req);
|
||||
dataObject.addExit(transportStopExit);
|
||||
codedIS.popLimit(oldLimit);
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
|
@ -555,4 +598,44 @@ public class BinaryMapTransportReaderAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
private TransportStopExit readTransportStopExit(int cleft, int ctop, SearchRequest<TransportStop> req) throws IOException {
|
||||
|
||||
TransportStopExit dataObject = new TransportStopExit();
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
while (true) {
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
|
||||
switch (tag) {
|
||||
case 0:
|
||||
if (dataObject.getName("en").length() == 0) {
|
||||
dataObject.setEnName(Junidecode.unidecode(dataObject.getName()));
|
||||
}
|
||||
if (x != 0 || y != 0) {
|
||||
dataObject.setLocation(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, x, y);
|
||||
}
|
||||
return dataObject;
|
||||
case OsmandOdb.TransportStopExit.REF_FIELD_NUMBER:
|
||||
if (req.stringTable != null) {
|
||||
dataObject.setRef(regStr(req.stringTable));
|
||||
} else {
|
||||
skipUnknownField(t);
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.TransportStopExit.DX_FIELD_NUMBER:
|
||||
x = codedIS.readSInt32() + cleft;
|
||||
break;
|
||||
case OsmandOdb.TransportStopExit.DY_FIELD_NUMBER:
|
||||
y = codedIS.readSInt32() + ctop;
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -77,6 +77,15 @@ public abstract class MapObject implements Comparable<MapObject> {
|
|||
}
|
||||
}
|
||||
|
||||
public void setNames(Map<String, String> name) {
|
||||
if (name != null) {
|
||||
if (names == null) {
|
||||
names = new HashMap<String, String>();
|
||||
}
|
||||
names.putAll(name);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getNamesMap(boolean includeEn) {
|
||||
if (!includeEn || Algorithms.isEmpty(enName)) {
|
||||
if (names == null) {
|
||||
|
|
|
@ -2,13 +2,20 @@ package net.osmand.data;
|
|||
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TransportStop extends MapObject {
|
||||
private int[] referencesToRoutes = null;
|
||||
private Amenity amenity;
|
||||
public int distance;
|
||||
public int x31;
|
||||
public int y31;
|
||||
|
||||
private List<TransportStopExit> exits;
|
||||
private HashMap<String,String> names;
|
||||
|
||||
public TransportStop(){
|
||||
}
|
||||
|
@ -39,4 +46,35 @@ public class TransportStop extends MapObject {
|
|||
y31 = dy << (31 - zoom);
|
||||
setLocation(MapUtils.getLatitudeFromTile(zoom, dy), MapUtils.getLongitudeFromTile(zoom, dx));
|
||||
}
|
||||
|
||||
public void addExit(TransportStopExit transportStopExit) {
|
||||
if (exits == null) {
|
||||
exits = new ArrayList<>();
|
||||
}
|
||||
exits.add(transportStopExit);
|
||||
}
|
||||
|
||||
public List<TransportStopExit> getExits () {
|
||||
if (exits == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return this.exits;
|
||||
}
|
||||
|
||||
public String getExitsString () {
|
||||
String exitsString = "";
|
||||
String refString = "";
|
||||
if (this.exits != null) {
|
||||
int i = 1;
|
||||
exitsString = exitsString + " Exits: [";
|
||||
for (TransportStopExit e : this.exits ) {
|
||||
if (e.getRef() != null) {
|
||||
refString = " [ref:" + e.getRef() + "] ";
|
||||
}
|
||||
exitsString = exitsString + " " + i + ")" + refString + e.getName() + " " + e.getLocation() + " ]";
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return exitsString;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package net.osmand.data;
|
||||
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
public class TransportStopExit extends MapObject {
|
||||
public int x31;
|
||||
public int y31;
|
||||
public String ref = null;
|
||||
@Override
|
||||
public void setLocation(double latitude, double longitude) {
|
||||
super.setLocation(latitude, longitude);
|
||||
}
|
||||
public void setLocation(int zoom, int dx, int dy) {
|
||||
x31 = dx << (31 - zoom);
|
||||
y31 = dy << (31 - zoom);
|
||||
setLocation(MapUtils.getLatitudeFromTile(zoom, dy), MapUtils.getLongitudeFromTile(zoom, dx));
|
||||
}
|
||||
public void setRef (String ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
public String getRef() {
|
||||
if (ref != null) {
|
||||
return ref;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -435,7 +435,6 @@ public class TileSourceManager {
|
|||
public static java.util.List<TileSourceTemplate> getKnownSourceTemplates() {
|
||||
java.util.List<TileSourceTemplate> list = new ArrayList<TileSourceTemplate>();
|
||||
list.add(getMapnikSource());
|
||||
list.add(getCycleMapSource());
|
||||
list.add(getMapillaryRasterSource());
|
||||
list.add(getMapillaryVectorSource());
|
||||
return list;
|
||||
|
@ -445,9 +444,6 @@ public class TileSourceManager {
|
|||
return MAPNIK_SOURCE;
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getCycleMapSource(){
|
||||
return CYCLE_MAP_SOURCE;
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getMapillaryRasterSource() {
|
||||
return MAPILLARY_RASTER_SOURCE;
|
||||
|
|
|
@ -13,6 +13,7 @@ public class OSMSettings {
|
|||
BOUNDARY("boundary"), //$NON-NLS-1$
|
||||
POSTAL_CODE("postal_code"), //$NON-NLS-1$
|
||||
RAILWAY("railway"), //$NON-NLS-1$
|
||||
STATION("subway"), //$NON-NLS-1$
|
||||
ONEWAY("oneway"), //$NON-NLS-1$
|
||||
LAYER("layer"), //$NON-NLS-1$
|
||||
BRIDGE("bridge"), //$NON-NLS-1$
|
||||
|
|
BIN
OsmAnd-telegram/res/drawable-hdpi/ic_action_altitude_range.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
OsmAnd-telegram/res/drawable-hdpi/ic_action_date_add.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
OsmAnd-telegram/res/drawable-hdpi/ic_action_date_end.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
OsmAnd-telegram/res/drawable-hdpi/ic_action_date_start.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
OsmAnd-telegram/res/drawable-hdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
OsmAnd-telegram/res/drawable-hdpi/ic_action_speed_average.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
OsmAnd-telegram/res/drawable-hdpi/ic_action_timeline.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
OsmAnd-telegram/res/drawable-mdpi/ic_action_altitude_range.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
OsmAnd-telegram/res/drawable-mdpi/ic_action_date_add.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
OsmAnd-telegram/res/drawable-mdpi/ic_action_date_end.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
OsmAnd-telegram/res/drawable-mdpi/ic_action_date_start.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
OsmAnd-telegram/res/drawable-mdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
OsmAnd-telegram/res/drawable-mdpi/ic_action_speed_average.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
OsmAnd-telegram/res/drawable-mdpi/ic_action_timeline.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
OsmAnd-telegram/res/drawable-xhdpi/ic_action_altitude_range.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
OsmAnd-telegram/res/drawable-xhdpi/ic_action_date_add.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
OsmAnd-telegram/res/drawable-xhdpi/ic_action_date_end.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
OsmAnd-telegram/res/drawable-xhdpi/ic_action_date_start.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
OsmAnd-telegram/res/drawable-xhdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
OsmAnd-telegram/res/drawable-xhdpi/ic_action_speed_average.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
OsmAnd-telegram/res/drawable-xhdpi/ic_action_timeline.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
OsmAnd-telegram/res/drawable-xxhdpi/ic_action_altitude_range.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
OsmAnd-telegram/res/drawable-xxhdpi/ic_action_date_add.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
OsmAnd-telegram/res/drawable-xxhdpi/ic_action_date_end.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
OsmAnd-telegram/res/drawable-xxhdpi/ic_action_date_start.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
OsmAnd-telegram/res/drawable-xxhdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
OsmAnd-telegram/res/drawable-xxhdpi/ic_action_speed_average.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
OsmAnd-telegram/res/drawable-xxhdpi/ic_action_timeline.png
Normal file
After Width: | Height: | Size: 2 KiB |
24
OsmAnd-telegram/res/drawable/btn_round_border.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/ctrl_active_light" />
|
||||
<corners android:radius="@dimen/dialog_button_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="false">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/ctrl_light" />
|
||||
<corners android:radius="@dimen/dialog_button_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@null" />
|
||||
<corners android:radius="@dimen/dialog_button_radius" />
|
||||
<stroke android:width="1dp" android:color="@color/app_bar_divider" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
184
OsmAnd-telegram/res/layout/fragment_timeline_tab.xml
Normal file
|
@ -0,0 +1,184 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:id="@+id/app_bar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/card_bg_color">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/title_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_bar_height"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/action_bar_height"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:letterSpacing="@dimen/title_letter_spacing"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
android:text="@string/timeline"
|
||||
android:textColor="@color/app_bar_title_light"
|
||||
android:textSize="@dimen/title_text_size"
|
||||
app:typeface="@string/font_roboto_mono_bold" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/options"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/content_padding_standard"
|
||||
android:layout_marginRight="@dimen/content_padding_standard"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half"
|
||||
tools:src="@drawable/ic_action_other_menu"
|
||||
tools:tint="@color/icon_light"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/action_bar_descr_bottom_margin"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
android:text="@string/timeline_description"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/descr_text_size" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/monitoring_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_bar_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/monitoring_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:text="@string/monitoring_is_enabled"
|
||||
android:textColor="@color/ctrl_active_light"
|
||||
android:textSize="@dimen/descr_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/monitoring_switcher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:focusable="false" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/app_bar_divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/date_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_header_height"
|
||||
android:background="@color/screen_bg_light"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/date_start_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_round_border"
|
||||
android:drawablePadding="@dimen/content_padding_half"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:text="@string/start_date"
|
||||
android:textColor="?attr/ctrl_active_color"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<View
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@color/app_bar_divider" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/date_end_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginStart="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_round_border"
|
||||
android:drawablePadding="@dimen/content_padding_half"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:text="@string/end_date"
|
||||
android:textColor="?attr/ctrl_active_color"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/last_telegram_update_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal"
|
||||
android:gravity="center"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
android:visibility="gone"
|
||||
app:typeface="@string/font_roboto_regular" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="@dimen/list_item_content_margin"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
509
OsmAnd-telegram/res/layout/fragment_user_gpx_info.xml
Normal file
|
@ -0,0 +1,509 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/card_bg_color">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/image_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
app:layout_scrollFlags="scroll">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginTop="@dimen/content_padding_standard"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/shared_string_back"
|
||||
android:padding="@dimen/content_padding_standard"
|
||||
tools:src="@drawable/ic_arrow_back"
|
||||
tools:tint="@color/icon_light" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/user_icon"
|
||||
android:layout_width="@dimen/my_location_user_icon_size"
|
||||
android:layout_height="@dimen/my_location_user_icon_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="@dimen/content_padding_standard"
|
||||
tools:src="@drawable/img_user_picture" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:text="@string/start_location_sharing"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/title_text_size"
|
||||
app:typeface="@string/font_roboto_mono_bold" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/interval_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/start_descr"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/content_padding_standard"
|
||||
android:layout_marginRight="@dimen/content_padding_standard"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/start_date"
|
||||
android:textColor="?attr/android:textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
app:firstBaselineToTopHeight="@dimen/list_item_baseline_to_top_height"
|
||||
app:typeface="@string/font_roboto_regular" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/end_descr"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginLeft="@dimen/content_padding_standard"
|
||||
android:layout_marginStart="@dimen/content_padding_standard"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/end_date"
|
||||
android:textColor="?attr/android:textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
app:firstBaselineToTopHeight="@dimen/list_item_baseline_to_top_height"
|
||||
app:typeface="@string/font_roboto_regular" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_header_height"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/date_start_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_round"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:textColor="?attr/ctrl_active_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/time_start_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@drawable/btn_round"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:textColor="?attr/ctrl_active_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<View
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="@color/card_divider_light" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/date_end_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_round"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:textColor="?attr/ctrl_active_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/time_end_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@drawable/btn_round"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:textColor="?attr/ctrl_active_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/map_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="152dp"
|
||||
android:layout_marginLeft="@dimen/content_padding_standard"
|
||||
android:layout_marginRight="@dimen/content_padding_standard">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/gpx_map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/shared_string_map" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gpx_statistic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/distance_time_span"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="11dp"
|
||||
android:paddingTop="13dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/distance_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:src="@drawable/ic_action_polygom_dark" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/distance_desc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:background="@null"
|
||||
android:text="@string/shared_string_distance"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/distance_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="40 km"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/duration_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:src="@drawable/ic_action_share_location" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/duration_desc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:background="@null"
|
||||
android:text="@string/time_on_the_move"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/duration_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="3:32:44"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/list_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/card_divider_light" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/card_divider_light" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/start_end_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="11dp"
|
||||
android:paddingTop="13dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/average_speed_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:src="@drawable/ic_action_speed_average" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/average_speed_desc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@null"
|
||||
android:text="@string/average_speed"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/average_speed_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="15:04:58"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/average_altitude_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:src="@drawable/ic_action_share_location" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/average_altitude_desc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@null"
|
||||
android:text="@string/average_altitude"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/average_altitude_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="20:58:00"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/open_in_osmand_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_item_height_min"
|
||||
android:layout_marginBottom="@dimen/content_padding_standard"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="@drawable/btn_round"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/open_in_osmand_icon"
|
||||
android:layout_width="@dimen/list_item_icon_size"
|
||||
android:layout_height="@dimen/list_item_icon_size"
|
||||
android:src="@drawable/ic_logo_osmand_free" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/open_in_osmand_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding_big"
|
||||
android:layout_marginRight="@dimen/content_padding_big"
|
||||
android:text="@string/open_in_osmand"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/list_item_title_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/share_gpx_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_item_height_min"
|
||||
android:layout_marginBottom="@dimen/content_padding_standard"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="@drawable/btn_round"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/share_gpx_icon"
|
||||
android:layout_width="@dimen/list_item_icon_size"
|
||||
android:layout_height="@dimen/list_item_icon_size"
|
||||
android:src="@drawable/ic_action_share"
|
||||
android:tint="@color/ctrl_active_light" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/share_gpx_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding_big"
|
||||
android:layout_marginRight="@dimen/content_padding_big"
|
||||
android:text="@string/shared_string_share"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/list_item_title_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
|
@ -9,4 +9,9 @@
|
|||
android:id="@+id/action_live_now"
|
||||
android:icon="@drawable/ic_action_live_now"
|
||||
android:title="@string/live_now"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_timeline"
|
||||
android:icon="@drawable/ic_action_timeline"
|
||||
android:title="@string/timeline"/>
|
||||
</menu>
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources><string name="last_update_from_telegram">Апошняе абнаўленне з Telegram</string>
|
||||
<string name="enter_another_device_name">Абярыце імя, якое вы яшчэ не выкарыстоўвалі</string>
|
||||
<string name="device_added_successfully">%1$s дададзена.</string>
|
||||
|
@ -10,7 +10,7 @@
|
|||
<string name="device_name">Назва прылады</string>
|
||||
<string name="shared_string_hide">Схаваць</string>
|
||||
<string name="share_location_as_description_second_line">Вы можаце стварыць і праглядзець ідэнтыфікатар прылады ў кліенце Тэлеграма, выкарыстоўваючы %1$s бота. %2$s</string>
|
||||
<string name="share_location_as_description">Калі вы хочаце падлучыць некалькі прылад да аднаго рахунка тэлеграм, то вам неабходна выкарыстаць розныя прылады, каб падзяліцца месцазнаходжаннем.</string>
|
||||
<string name="share_location_as_description">Калі вы хочаце падлучыць некалькі прылад да аднаго акаўнта тэлеграм, то вам неабходна выкарыстаць розныя прылады, каб падзяліцца месцазнаходжаннем.</string>
|
||||
<string name="last_updated_location">Апошняе абнаўленне месцазнаходжання:</string>
|
||||
<string name="successfully_sent_and_updated">Паспяхова адпраўлена і абноўлена</string>
|
||||
<string name="not_possible_to_send_to_telegram_chats">Немагчыма адправіць у размову Тэлеграм:</string>
|
||||
|
@ -61,7 +61,7 @@
|
|||
<string name="disconnect_from_telegram_desc">Для таго, каб скасаваць абмен месцазнаходжаннем, адкрыйце Тэлеграм, перайдзіце ў Налады → Прыватнасць і бяспека → Сеансы і спыніце сеанс OsmAnd Telegram.</string>
|
||||
<string name="disconnect_from_telegram">Як выключыць абмен месцазнаходжаннем у OsmAnd праз Тэлеграм</string>
|
||||
<string name="logout_help_desc">Як выключыць абмен месцазнаходжаннем у OsmAnd праз Тэлеграм</string>
|
||||
<string name="connected_account">Падлучаны рахунак</string>
|
||||
<string name="connected_account">Падлучаны акаўнт</string>
|
||||
<string name="shared_string_account">Рахунак</string>
|
||||
<string name="in_time">у %1$s</string>
|
||||
<string name="osmand_connect_desc">Абраць версію OsmAnd, якую OsmAnd Telegram будзе выкарыстоўваць для адлюстравання пазіцыі.</string>
|
||||
|
@ -81,13 +81,13 @@
|
|||
<string name="shared_string_live">Дзейных</string>
|
||||
<string name="shared_string_bot">Бот</string>
|
||||
<string name="get_telegram_title">Рэгістрацыя ў Telegram</string>
|
||||
<string name="get_telegram_account_first">Для абмену вам неабходны рахунак Тэлеграм.</string>
|
||||
<string name="get_telegram_description_continue">Калі ласка, ўсталюйце Тэлеграм і наладзьце рахунак.</string>
|
||||
<string name="get_telegram_account_first">Для абмену вам неабходны акаўнт Тэлеграм.</string>
|
||||
<string name="get_telegram_description_continue">Калі ласка, ўсталюйце Тэлеграм і наладзьце акаўнт.</string>
|
||||
<string name="get_telegram_after_creating_account">Пасля гэтага вы зможаце выкарыстоўваць дадатак.</string>
|
||||
<string name="shared_string_all">Усе</string>
|
||||
<string name="shared_string_off">Выкл</string>
|
||||
<string name="already_registered_in_telegram">Вам неабходна мець рахунак Тэлеграм і нумар тэлефона</string>
|
||||
<string name="do_not_have_telegram">У мяне няма рахунка Тэлеграм</string>
|
||||
<string name="already_registered_in_telegram">Вам неабходна мець акаўнт Тэлеграм і нумар тэлефона</string>
|
||||
<string name="do_not_have_telegram">У мяне няма акаўнта Тэлеграм</string>
|
||||
<string name="enter_phone_number">Увядзіце нумар тэлефона</string>
|
||||
<string name="enter_authentication_code">Увядзіце код аўтарызацыі</string>
|
||||
<string name="set_visible_time_for_all">Вызначце бачны час для ўсіх</string>
|
||||
|
@ -110,7 +110,7 @@
|
|||
<string name="shared_string_password">Пароль</string>
|
||||
<string name="enter_code">Увядзіце код</string>
|
||||
<string name="authentication_code">Код аўтэнтыфікацыі</string>
|
||||
<string name="authentication_code_descr">Тэлеграм адправіў вам код для OsmAnd для ўваходу ў рахунак.</string>
|
||||
<string name="authentication_code_descr">Тэлеграм адправіў вам код для OsmAnd для ўваходу ў акаўнт.</string>
|
||||
<string name="enter_password">Увядзіце пароль</string>
|
||||
<string name="password_descr">Пароль Тэлеграм</string>
|
||||
<string name="shared_string_login">Увайсці</string>
|
||||
|
@ -167,7 +167,7 @@
|
|||
<string name="shared_string_hour_short">г</string>
|
||||
<string name="shared_string_minute_short">хвіл</string>
|
||||
<string name="shared_string_second_short">сек</string>
|
||||
<string name="welcome_descr"><b>Абмен месцазнаходжаннем OsmAnd</b> Дае магчымасць дзяліцца сваім месцазнаходжаннем і бачыць месцазнаходжанне іншых у OsmAnd.<br/><br/> Дадатак выкарыстоўвае Telegram API, таму вам неабходны рахунак Тэлеграм.</string>
|
||||
<string name="welcome_descr"><b>Абмен месцазнаходжаннем OsmAnd</b> Дае магчымасць дзяліцца сваім месцазнаходжаннем і бачыць месцазнаходжанне іншых у OsmAnd.<br/><br/> Дадатак выкарыстоўвае Telegram API, таму вам неабходны акаўнт Тэлеграм.</string>
|
||||
<string name="my_location">Маё месцазнаходжанне</string>
|
||||
<string name="live_now">Зараз дзейнічае</string>
|
||||
|
||||
|
|
|
@ -177,4 +177,14 @@
|
|||
<string name="shared_string_map">Mapa</string>
|
||||
<string name="shared_string_text">Texto</string>
|
||||
<string name="map_and_text">Mapa y texto</string>
|
||||
<string name="monitoring_is_enabled">Monitorización activada</string>
|
||||
<string name="monitoring_is_disabled">Monitorización desactivada</string>
|
||||
<string name="time_on_the_move">tiempo en movimiento</string>
|
||||
<string name="average_altitude">Altitud media</string>
|
||||
<string name="average_speed">Velocidad media</string>
|
||||
<string name="open_in_osmand">Abrir en OsmAnd</string>
|
||||
<string name="end_date">Fecha de finalización</string>
|
||||
<string name="start_date">Fecha de inicio</string>
|
||||
<string name="timeline_description">Activar la monitorización para recopilar datos de movimiento en segundo plano.</string>
|
||||
<string name="timeline">Línea de tiempo</string>
|
||||
</resources>
|
|
@ -177,4 +177,14 @@
|
|||
<string name="shared_string_map">Mapa</string>
|
||||
<string name="shared_string_text">Texto</string>
|
||||
<string name="map_and_text">Mapa y texto</string>
|
||||
<string name="monitoring_is_enabled">Monitorización activada</string>
|
||||
<string name="monitoring_is_disabled">Monitorización desactivada</string>
|
||||
<string name="time_on_the_move">tiempo en movimiento</string>
|
||||
<string name="average_altitude">Altitud media</string>
|
||||
<string name="average_speed">Velocidad media</string>
|
||||
<string name="open_in_osmand">Abrir en OsmAnd</string>
|
||||
<string name="end_date">Fecha de fin</string>
|
||||
<string name="start_date">Fecha de inicio</string>
|
||||
<string name="timeline_description">Activar la monitorización para recopilar datos de movimiento en segundo plano.</string>
|
||||
<string name="timeline">Línea de tiempo</string>
|
||||
</resources>
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources><string name="background_work_description">Endre batterioptimiseringsinnstillinger for mer stabil posisjonsdeling.</string>
|
||||
<string name="background_work">Bakgrunnsarbeid</string>
|
||||
<string name="battery_optimization_description">Skru av batterioptimisering for OsmAnd Telegram slik at det ikke plutselig skrur seg av når det er i bakgrunnen.</string>
|
||||
|
@ -179,4 +179,14 @@
|
|||
<string name="shared_string_map">Kart</string>
|
||||
<string name="shared_string_text">Tekst</string>
|
||||
<string name="map_and_text">Kart og tekst</string>
|
||||
</resources>
|
||||
<string name="monitoring_is_enabled">Oppsyn er påskrudd</string>
|
||||
<string name="monitoring_is_disabled">Oppsyn er avskrudd</string>
|
||||
<string name="time_on_the_move">tid i bevegelse</string>
|
||||
<string name="average_altitude">Gjennomsnittlig høyde</string>
|
||||
<string name="average_speed">Gjennomsnittsfart</string>
|
||||
<string name="open_in_osmand">Åpne i OsmAnd</string>
|
||||
<string name="end_date">Sluttdato</string>
|
||||
<string name="start_date">Startdato</string>
|
||||
<string name="timeline_description">Skru på oppsyn for å samle bevegelsesdata i bakgrunnen.</string>
|
||||
<string name="timeline">Tidslinje</string>
|
||||
</resources>
|
177
OsmAnd-telegram/res/values-pt-rBR/strings.xml
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources><string name="send_location_as">Enviar localização como</string>
|
||||
<string name="send_location_as_descr">Escolha como as mensagens com sua localização serão exibidas.</string>
|
||||
<string name="shared_string_map">Mapa</string>
|
||||
<string name="shared_string_text">Texto</string>
|
||||
<string name="map_and_text">Mapa e texto</string>
|
||||
<string name="last_update_from_telegram">Última atualização do Telegram</string>
|
||||
<string name="enter_another_device_name">Escolha um nome que você ainda não usou</string>
|
||||
<string name="device_added_successfully">%1$s adicionado.</string>
|
||||
<string name="shared_string_add">Adicionar</string>
|
||||
<string name="error_adding_new_device">Não foi possível adicionar novo dispositivo</string>
|
||||
<string name="enter_device_name_description">Nomeie seu novo dispositivo no máximo 200 símbolos.</string>
|
||||
<string name="device_name_is_too_long">Nome do dispositivo muito longo</string>
|
||||
<string name="device_name_cannot_be_empty">O nome do dispositivo não pode estar vazio</string>
|
||||
<string name="device_name">Nome do dispositivo</string>
|
||||
<string name="shared_string_hide">Ocultar</string>
|
||||
<string name="share_location_as_description_second_line">Você pode criar e visualizar o ID do dispositivo no cliente de telegrama usando o bot de bate-papo %1$s. %2$s</string>
|
||||
<string name="share_location_as_description">Se você deseja conectar vários dispositivos a uma conta de telegrama, é necessário usar um dispositivo diferente para compartilhar sua localização.</string>
|
||||
<string name="last_updated_location">Última localização atualizada:</string>
|
||||
<string name="successfully_sent_and_updated">Enviado e atualizado com sucesso</string>
|
||||
<string name="not_possible_to_send_to_telegram_chats">Não é possível enviar para bate-papo do Telegram:</string>
|
||||
<string name="waiting_for_response_from_telegram">Aguardando resposta do Telegram</string>
|
||||
<string name="sending_location_messages">enviando localização</string>
|
||||
<string name="initializing">Iniciando</string>
|
||||
<string name="searching_for_gps">Posicionando…</string>
|
||||
<string name="connecting_to_the_internet">Conectando-se à Internet</string>
|
||||
<string name="background_work_description">Altere as configurações de otimização da bateria para estabilizar o compartilhamento de local.</string>
|
||||
<string name="background_work">Trabalho de fundo</string>
|
||||
<string name="battery_optimization_description">Desative a otimização da bateria do OsmAnd Telegram para que não seja desligado repentinamente quando estiver em segundo plano.</string>
|
||||
<string name="sharing_in_background">Compartilhando em segundo plano</string>
|
||||
<string name="go_to_settings">Vá para as configurações</string>
|
||||
<string name="shared_string_later">Mais tarde</string>
|
||||
<string name="not_sent_yet">Ainda não enviado</string>
|
||||
<string name="not_found_yet">Ainda não encontrado</string>
|
||||
<string name="re_send_location">Reenvie o local</string>
|
||||
<string name="last_available_location">Última localização disponível</string>
|
||||
<string name="sharing_status">Status de compartilhamento</string>
|
||||
<string name="sharing_enabled">Compartilhamento: Ativado</string>
|
||||
<string name="shared_string_status">Status</string>
|
||||
<string name="no_gps_connection">Sem conexão GPS</string>
|
||||
<string name="no_internet_connection">Sem conexão com a internet</string>
|
||||
<string name="shared_string_disable">Desabilitar</string>
|
||||
<string name="shared_string_save">Salvar</string>
|
||||
<string name="add_device">Adicionar dispositivo</string>
|
||||
<string name="share_location_as">Compartilhar localização como</string>
|
||||
<string name="live_now_description">Contatos e grupos compartilhando o local para você.</string>
|
||||
<string name="logout_from_osmand_telegram_descr">Tem certeza de que deseja sair do OsmAnd Telegram para que você não possa compartilhar a localização ou ver a localização de outras pessoas\?</string>
|
||||
<string name="logout_from_osmand_telegram">Sair do OsmAnd Telegram\?</string>
|
||||
<string name="shared_string_name">Nome</string>
|
||||
<string name="by_distance">Pela distância</string>
|
||||
<string name="by_name">Por nome</string>
|
||||
<string name="by_group">Por grupo</string>
|
||||
<string name="shared_string_sort">Ordenar</string>
|
||||
<string name="shared_string_sort_by">Classificar por</string>
|
||||
<string name="choose_osmand_desc">Selecione a versão OsmAnd, onde os contatos serão exibidos no mapa.</string>
|
||||
<string name="choose_osmand">Selecione a versão do OsmAnd para usar</string>
|
||||
<string name="disable_all_sharing_desc">Desativa o compartilhamento de local para todos os bate-papos selecionados (%1$d).</string>
|
||||
<string name="disable_all_sharing">Desativar todo o compartilhamento</string>
|
||||
<string name="turn_off_all">Desligue todos</string>
|
||||
<string name="shared_string_exit">Sair</string>
|
||||
<string name="time_ago">atrás</string>
|
||||
<string name="last_response">Última resposta</string>
|
||||
<string name="shared_string_group">Grupo</string>
|
||||
<string name="logout_no_internet_msg">Conecte-se à Internet para efetuar a saída do Telegram corretamente.</string>
|
||||
<string name="shared_string_close">Fechar</string>
|
||||
<string name="disconnect_from_telegram_desc">Para revogar o acesso ao compartilhamento de local. Abra o Telegram, vá para Configurações → Privacidade e Segurança → Sessões e termine a sessão do OsmAnd Telegram.</string>
|
||||
<string name="disconnect_from_telegram">"Como desativar o compartilhamento de local do OsmAnd para Telegram"</string>
|
||||
<string name="logout_help_desc">"Como desativar o compartilhamento de local do OsmAnd para Telegram"</string>
|
||||
<string name="connected_account">Conta conectada</string>
|
||||
<string name="shared_string_account">Conta</string>
|
||||
<string name="in_time">no %1$s</string>
|
||||
<string name="osmand_connect_desc">Escolha a versão OsmAnd que OsmAnd Telegram usa para exibir posições.</string>
|
||||
<string name="osmand_connect">"conectar ao OsmAnd "</string>
|
||||
<string name="location_history_desc">Ocultar contatos que não foram movidos em um determinado momento.</string>
|
||||
<string name="location_history">Histórico de localização</string>
|
||||
<string name="stale_location_desc">A última vez que um contato foi movido.</string>
|
||||
<string name="stale_location">Parado</string>
|
||||
<string name="send_my_location_desc">Defina o intervalo mínimo para o compartilhamento de local.</string>
|
||||
<string name="send_my_location">Enviar minha localização</string>
|
||||
<string name="gps_and_location">Posição</string>
|
||||
<string name="sharing_time">Tempo de compartilhamento</string>
|
||||
<string name="expire_at">Expira</string>
|
||||
<string name="stop_sharing_all">O compartilhamento está ativado (desativado)</string>
|
||||
<string name="turn_off_location_sharing">Desativar o compartilhamento de local</string>
|
||||
<string name="open_osmand">Abrir OsmAnd</string>
|
||||
<string name="shared_string_live">Vivo</string>
|
||||
<string name="shared_string_bot">Robô</string>
|
||||
<string name="get_telegram_title">Registro no Telegram</string>
|
||||
<string name="get_telegram_account_first">Você precisa de uma conta do Telegram para usar o compartilhamento de local.</string>
|
||||
<string name="get_telegram_description_continue">Por favor, instale o Telegram e configure uma conta.</string>
|
||||
<string name="get_telegram_after_creating_account">Então você pode usar este aplicativo.</string>
|
||||
<string name="shared_string_all">Todos</string>
|
||||
<string name="shared_string_off">Desativado</string>
|
||||
<string name="already_registered_in_telegram">Você precisa de uma conta e número de telefone registrados no Telegram</string>
|
||||
<string name="do_not_have_telegram">Eu não tenho conta Telegram</string>
|
||||
<string name="enter_phone_number">Digite o número de telefone</string>
|
||||
<string name="enter_authentication_code">Digite o código de autenticação</string>
|
||||
<string name="set_visible_time_for_all">Definir tempo visível para todos</string>
|
||||
<string name="hours_and_minutes_format">%1$d h %2$d m</string>
|
||||
<string name="minutes_format">%1$d m</string>
|
||||
<string name="hours_format">%1$d h</string>
|
||||
<string name="shared_string_install">Instalar</string>
|
||||
<string name="shared_string_share">Compartilhar</string>
|
||||
<string name="shared_string_back">Voltar</string>
|
||||
<string name="visible_time_for_all">Hora visível para todos</string>
|
||||
<string name="set_time_description">Defina a hora em que seus contatos e grupos selecionados verão sua localização em tempo real.</string>
|
||||
<string name="set_time">Definir tempo</string>
|
||||
<string name="location_sharing_description">Selecione os contatos e grupos com os quais você deseja compartilhar sua localização.</string>
|
||||
<string name="my_location_search_hint">Pesquisa: Grupo ou contato</string>
|
||||
<string name="start_location_sharing">Compartilhar localização</string>
|
||||
<string name="show_on_map">Mostrar no mapa</string>
|
||||
<string name="app_name">OsmAnd Telegram</string>
|
||||
<string name="phone_number_title">Número de telefone</string>
|
||||
<string name="phone_number_descr">Número de telefone no formato internacional</string>
|
||||
<string name="shared_string_password">Senha</string>
|
||||
<string name="enter_code">Coloque o código</string>
|
||||
<string name="authentication_code">Código de Autenticação</string>
|
||||
<string name="authentication_code_descr">Uma faixa GPX é salva automaticamente durante a navegação.</string>
|
||||
<string name="enter_password">Digite a senha</string>
|
||||
<string name="password_descr">Senha do telegrama</string>
|
||||
<string name="shared_string_login">Entrar</string>
|
||||
<string name="shared_string_logout">Sair</string>
|
||||
<string name="initialization">Iniciando</string>
|
||||
<string name="logging_out">Saindo</string>
|
||||
<string name="closing">Fechando</string>
|
||||
<string name="gps_network_not_enabled">Ativar \"Localização\"\?</string>
|
||||
<string name="not_logged_in">você não está logado no</string>
|
||||
<string name="shared_string_continue">Continuar</string>
|
||||
<string name="shared_string_cancel">Cancelar</string>
|
||||
<string name="shared_string_settings">Configurações</string>
|
||||
<string name="no_location_permission">O aplicativo não tem permissão para acessar os dados de localização.</string>
|
||||
<string name="gps_not_available">Por favor, ligue \"Localização\" nas configurações do sistema</string>
|
||||
<string name="location_service_no_gps_available">Selecione um dos provedores de localização para compartilhar sua localização.</string>
|
||||
<string name="osmand_service">Modo em segundo plano</string>
|
||||
<string name="osmand_service_descr">OsmAnd Telegram é executado em segundo plano com a tela desligada.</string>
|
||||
<string name="shared_string_distance">Distância</string>
|
||||
<string name="share_location">Compartilhar localização</string>
|
||||
<string name="sharing_location">Compartilhando localização</string>
|
||||
<string name="process_service">Serviço OsmAnd Telegram</string>
|
||||
<string name="osmand_logo">Logotipo do OsmAnd</string>
|
||||
<string name="install_osmand_dialog_message">Você precisa instalar a versão gratuita ou paga do OsmAnd primeiro</string>
|
||||
<string name="install_osmand">Instalar OsmAnd</string>
|
||||
<string name="show_users_on_map">Mostrar usuários no mapa</string>
|
||||
<string name="active_chats">Bate-papos ativos</string>
|
||||
<string name="shared_string_authorization">Autorização</string>
|
||||
<string name="shared_string_authorization_descr">Por favor, insira o número de telefone do seu Telegram em formato internacional</string>
|
||||
<string name="shared_string_welcome">Boas vindas</string>
|
||||
<string name="yard">yd</string>
|
||||
<string name="foot">ft</string>
|
||||
<string name="mile">mi</string>
|
||||
<string name="km">km</string>
|
||||
<string name="m">m</string>
|
||||
<string name="nm">mn</string>
|
||||
<string name="min_mile">min/m</string>
|
||||
<string name="min_km">min/km</string>
|
||||
<string name="nm_h">mn/h</string>
|
||||
<string name="m_s">m/s</string>
|
||||
<string name="km_h">km/h</string>
|
||||
<string name="mile_per_hour">mph</string>
|
||||
<string name="si_kmh">Quilômetros por hora</string>
|
||||
<string name="si_mph">Milhas por hora</string>
|
||||
<string name="si_m_s">Metros por segundo</string>
|
||||
<string name="si_min_km">Minutos por quilômetro</string>
|
||||
<string name="si_min_m">Minutos por milha</string>
|
||||
<string name="si_nm_h">Milhas náuticas por hora (nó)</string>
|
||||
<string name="si_mi_feet">Milhas/pés</string>
|
||||
<string name="si_mi_yard">Milhas/jardas</string>
|
||||
<string name="si_km_m">Quilômetros/metros</string>
|
||||
<string name="si_nm">Milhas náuticas</string>
|
||||
<string name="si_mi_meters">Milhas/metros</string>
|
||||
<string name="shared_string_hour_short">h</string>
|
||||
<string name="shared_string_minute_short">min</string>
|
||||
<string name="shared_string_second_short">seg</string>
|
||||
<string name="welcome_descr"><b>Compartilhamento de local OsmAnd</b> permite que você compartilhe sua localização e veja a dos outros no OsmAnd.<br/><br/>O aplicativo usa a API Telegram e você precisa de uma conta Telegram.</string>
|
||||
<string name="my_location">Minha localização</string>
|
||||
<string name="live_now">Ao vivo agora</string>
|
||||
</resources>
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources>
|
||||
<string name="timeline_description">Включите мониторинг, для сбора данных о перемещении в фоновом режиме.</string>
|
||||
<string name="last_update_from_telegram">Последнее обновление в Telegram</string>
|
||||
<string name="device_name">Имя устройства</string>
|
||||
<string name="shared_string_hide">Спрятать</string>
|
||||
|
|
178
OsmAnd-telegram/res/values-zh-rTW/strings.xml
Normal file
|
@ -0,0 +1,178 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources><string name="send_location_as">傳送位置為</string>
|
||||
<string name="send_location_as_descr">選擇您所在位置怎樣的訊息外觀。</string>
|
||||
<string name="shared_string_map">地圖</string>
|
||||
<string name="shared_string_text">文字</string>
|
||||
<string name="map_and_text">地圖與文字</string>
|
||||
<string name="device_added_successfully">%1$s 已新增。</string>
|
||||
<string name="shared_string_add">新增</string>
|
||||
<string name="error_adding_new_device">無法增加新的裝置</string>
|
||||
<string name="enter_device_name_description">命名您的新裝置,最多 200 個字符。</string>
|
||||
<string name="device_name_is_too_long">裝置名稱太長</string>
|
||||
<string name="device_name_cannot_be_empty">裝置名稱不能為空白</string>
|
||||
<string name="device_name">裝置名稱</string>
|
||||
<string name="shared_string_hide">隱藏</string>
|
||||
<string name="last_updated_location">上次更新的位置:</string>
|
||||
<string name="sending_location_messages">正在傳送位置</string>
|
||||
<string name="initializing">正在啟動</string>
|
||||
<string name="searching_for_gps">正在定位…</string>
|
||||
<string name="connecting_to_the_internet">正在連線至網路</string>
|
||||
<string name="background_work">背景工作</string>
|
||||
<string name="sharing_in_background">在背景分享</string>
|
||||
<string name="go_to_settings">轉至設定</string>
|
||||
<string name="shared_string_later">隨後</string>
|
||||
<string name="not_sent_yet">尚未傳送</string>
|
||||
<string name="not_found_yet">尚未找到</string>
|
||||
<string name="re_send_location">重新傳送位置</string>
|
||||
<string name="last_available_location">最後可用的位置</string>
|
||||
<string name="sharing_status">分享狀態</string>
|
||||
<string name="sharing_enabled">分享:已啟用</string>
|
||||
<string name="shared_string_status">狀態</string>
|
||||
<string name="no_gps_connection">沒有 GPS 連接</string>
|
||||
<string name="no_internet_connection">沒有網際網路連線</string>
|
||||
<string name="shared_string_disable">停用</string>
|
||||
<string name="shared_string_save">儲存</string>
|
||||
<string name="add_device">新增裝置</string>
|
||||
<string name="share_location_as">分享位置為</string>
|
||||
<string name="shared_string_name">名稱</string>
|
||||
<string name="by_distance">按距離</string>
|
||||
<string name="by_name">按名稱</string>
|
||||
<string name="by_group">按群組</string>
|
||||
<string name="shared_string_sort">分類</string>
|
||||
<string name="shared_string_sort_by">排序方式</string>
|
||||
<string name="disable_all_sharing">停用所有分享</string>
|
||||
<string name="turn_off_all">關閉全部</string>
|
||||
<string name="shared_string_exit">離開</string>
|
||||
<string name="last_update_from_telegram">Telegram 的最後一次更新</string>
|
||||
<string name="enter_another_device_name">選擇一個尚未使用的名稱</string>
|
||||
<string name="share_location_as_description_second_line">您可以使用 %1$s 聊天機器人在電報用戶端中創建和查看裝置 ID。 %2$s</string>
|
||||
<string name="share_location_as_description">如果要將多個設備連接到一個 Telegram 帳戶,則需要使用不同的設備來共用您的位置。</string>
|
||||
<string name="successfully_sent_and_updated">已成功發送和更新</string>
|
||||
<string name="not_possible_to_send_to_telegram_chats">無法發送到 Telegram 聊天:</string>
|
||||
<string name="waiting_for_response_from_telegram">等待 Telegram 回復</string>
|
||||
<string name="background_work_description">更改電池最佳化設置以穩定位置共用。</string>
|
||||
<string name="battery_optimization_description">關閉 OsmAnd Telegram 的電池最佳化,這樣在後臺時就不會突然關閉。</string>
|
||||
<string name="live_now_description">連絡人和群組共用位置給您。</string>
|
||||
<string name="logout_from_osmand_telegram_descr">你確定要登出 OsmAnd Telegram,這樣你就不能共用位置或看到其他人的位置嗎?</string>
|
||||
<string name="logout_from_osmand_telegram">要登出 OsmAnd Telegram 嗎\?</string>
|
||||
<string name="choose_osmand_desc">選擇將在地圖上顯示連絡人的 OsmAnd 版本。</string>
|
||||
<string name="choose_osmand">選擇要使用的 OsmAnd 版本</string>
|
||||
<string name="disable_all_sharing_desc">關閉所有選定聊天的位置共用(%1$d)。</string>
|
||||
<string name="time_ago">前</string>
|
||||
<string name="last_response">上次回應</string>
|
||||
<string name="shared_string_group">群組</string>
|
||||
<string name="logout_no_internet_msg">連接到網路以正確登出 Telegram。</string>
|
||||
<string name="shared_string_close">關閉</string>
|
||||
<string name="disconnect_from_telegram_desc">撤銷位置共用訪問。打開 Telegram,進入設定→隱私和安全→會話,並終 OsmAnd Telegram 會話。</string>
|
||||
<string name="disconnect_from_telegram">如何關閉 Telegram 中的 OsmAnd 交給位置共用</string>
|
||||
<string name="logout_help_desc">如何關閉 Telegram 中的 OsmAnd 交給位置共用</string>
|
||||
<string name="connected_account">已連接帳戶</string>
|
||||
<string name="shared_string_account">帳戶</string>
|
||||
<string name="in_time">在 %1$s</string>
|
||||
<string name="osmand_connect_desc">選擇 OsmAnd 和版本的 OsmAnd Telegram 用於顯示位置。</string>
|
||||
<string name="osmand_connect">OsMand 連接</string>
|
||||
<string name="location_history_desc">隱藏在給定時間內未移動的連絡人。</string>
|
||||
<string name="location_history">位置歷史記錄</string>
|
||||
<string name="stale_location_desc">上次移動連絡人的時間。</string>
|
||||
<string name="stale_location">沒有移動
|
||||
\n</string>
|
||||
<string name="send_my_location_desc">設置位置共用的最小間隔。</string>
|
||||
<string name="send_my_location">發送我的位置</string>
|
||||
<string name="gps_and_location">位置</string>
|
||||
<string name="sharing_time">共用時間</string>
|
||||
<string name="expire_at">到期</string>
|
||||
<string name="stop_sharing_all">共用已打開 (關閉)</string>
|
||||
<string name="turn_off_location_sharing">關閉位置共用</string>
|
||||
<string name="open_osmand">打開 OsmAnd</string>
|
||||
<string name="shared_string_live">即時</string>
|
||||
<string name="shared_string_bot">提供</string>
|
||||
<string name="get_telegram_title">註冊 Telegram</string>
|
||||
<string name="get_telegram_account_first">您需要一個 Telegram 帳戶才能使用位置共用。</string>
|
||||
<string name="get_telegram_description_continue">請安裝 Telegram 並建立帳戶。</string>
|
||||
<string name="get_telegram_after_creating_account">然後您可以使用這個應用程式。</string>
|
||||
<string name="shared_string_all">所有</string>
|
||||
<string name="shared_string_off">關閉</string>
|
||||
<string name="already_registered_in_telegram">你需要一個 Telegram 帳號和電話號碼</string>
|
||||
<string name="do_not_have_telegram">我沒有 Telegram 帳戶</string>
|
||||
<string name="enter_phone_number">添加電話號碼</string>
|
||||
<string name="enter_authentication_code">輸入身份驗證程式碼</string>
|
||||
<string name="set_visible_time_for_all">為所有人設定可見時間</string>
|
||||
<string name="hours_and_minutes_format">%1$d 時 %2$d 分</string>
|
||||
<string name="minutes_format">%1$d 分</string>
|
||||
<string name="hours_format">%1$d 時</string>
|
||||
<string name="shared_string_install">安裝</string>
|
||||
<string name="shared_string_share">分享</string>
|
||||
<string name="shared_string_back">返回</string>
|
||||
<string name="visible_time_for_all">所有人的可見時間</string>
|
||||
<string name="set_time_description">設置所選連絡人和組即時查看您的位置的時間。</string>
|
||||
<string name="set_time">設定時間</string>
|
||||
<string name="location_sharing_description">選擇要共用位置的連絡人和群組。</string>
|
||||
<string name="my_location_search_hint">搜尋:群組或連絡人</string>
|
||||
<string name="start_location_sharing">共用位置</string>
|
||||
<string name="show_on_map">在地圖上顯示</string>
|
||||
<string name="app_name">OsmAnd Telegram</string>
|
||||
<string name="phone_number_title">電話號碼</string>
|
||||
<string name="phone_number_descr">國際格式的電話號碼</string>
|
||||
<string name="shared_string_password">密碼</string>
|
||||
<string name="enter_code">輸入代碼</string>
|
||||
<string name="authentication_code">身份驗證代碼</string>
|
||||
<string name="authentication_code_descr">Telegram 給你發了一個代碼,要求 OsmAnd 登入你的帳戶。</string>
|
||||
<string name="enter_password">輸入密碼</string>
|
||||
<string name="password_descr">Telegram 密碼</string>
|
||||
<string name="shared_string_login">登入</string>
|
||||
<string name="shared_string_logout">登出</string>
|
||||
<string name="initialization">正在啟動</string>
|
||||
<string name="logging_out">已登出</string>
|
||||
<string name="closing">關閉</string>
|
||||
<string name="gps_network_not_enabled">打開“位置”?</string>
|
||||
<string name="not_logged_in">您沒有登入</string>
|
||||
<string name="shared_string_continue">繼續</string>
|
||||
<string name="shared_string_cancel">取消</string>
|
||||
<string name="shared_string_settings">設定</string>
|
||||
<string name="no_location_permission">應用程式沒有存取位置數據的許可權。</string>
|
||||
<string name="gps_not_available">請在系統設置中打開“位置”</string>
|
||||
<string name="location_service_no_gps_available">選擇一個位置提供商來共享您的位置。</string>
|
||||
<string name="osmand_service">背景模式</string>
|
||||
<string name="osmand_service_descr">當螢幕關閉後,讓 OsmAnd 在背景運行。</string>
|
||||
<string name="shared_string_distance">距離</string>
|
||||
<string name="share_location">共用位置</string>
|
||||
<string name="sharing_location">共用位置</string>
|
||||
<string name="process_service">OsmAnd Telegram 伺服器</string>
|
||||
<string name="osmand_logo">OsmAnd 圖示</string>
|
||||
<string name="install_osmand_dialog_message">您需要先安裝免費或付費版本的 OsmAnd</string>
|
||||
<string name="install_osmand">安裝 OsMand</string>
|
||||
<string name="show_users_on_map">在地圖上顯示用戶</string>
|
||||
<string name="active_chats">主動聊天</string>
|
||||
<string name="shared_string_authorization">授權</string>
|
||||
<string name="shared_string_authorization_descr">請以國際格式輸入 Telegram 電話號碼</string>
|
||||
<string name="shared_string_welcome">歡迎</string>
|
||||
<string name="yard">碼</string>
|
||||
<string name="foot">呎</string>
|
||||
<string name="mile">哩</string>
|
||||
<string name="km">公里</string>
|
||||
<string name="m">公尺</string>
|
||||
<string name="nm">浬</string>
|
||||
<string name="min_mile">分/公尺</string>
|
||||
<string name="min_km">分/公里</string>
|
||||
<string name="nm_h">浬/時</string>
|
||||
<string name="m_s">公尺/秒</string>
|
||||
<string name="km_h">公里/小時</string>
|
||||
<string name="mile_per_hour">哩/小時</string>
|
||||
<string name="si_kmh">公里每小時</string>
|
||||
<string name="si_mph">英里每小時</string>
|
||||
<string name="si_m_s">公尺每秒</string>
|
||||
<string name="si_min_km">分鐘每公里</string>
|
||||
<string name="si_min_m">分鐘每英里</string>
|
||||
<string name="si_nm_h">浬每小時 (節)</string>
|
||||
<string name="si_mi_feet">英哩/英呎</string>
|
||||
<string name="si_mi_yard">英哩/碼</string>
|
||||
<string name="si_km_m">公里/公尺</string>
|
||||
<string name="si_nm">海浬</string>
|
||||
<string name="si_mi_meters">英里/米</string>
|
||||
<string name="shared_string_hour_short">時</string>
|
||||
<string name="shared_string_minute_short">分</string>
|
||||
<string name="shared_string_second_short">秒</string>
|
||||
<string name="welcome_descr"><b>OsmAnd 位置共用</b>可以讓您共用您的位置,並在 OsmAnd 中看到其他人的位置。<br/><br/>該應用程式使用電報 API,你需要一個 Telegram 帳戶。</string>
|
||||
<string name="my_location">我的位置</string>
|
||||
<string name="live_now">即時狀況</string>
|
||||
</resources>
|
|
@ -1,4 +1,13 @@
|
|||
<resources>
|
||||
<string name="monitoring_is_enabled">Monitoring is enabled</string>
|
||||
<string name="monitoring_is_disabled">Monitoring is disabled</string>
|
||||
<string name="time_on_the_move">time on the move</string>
|
||||
<string name="average_altitude">Average altitude</string>
|
||||
<string name="average_speed">Average speed</string>
|
||||
<string name="open_in_osmand">Open in OsmAnd</string>
|
||||
<string name="end_date">End date</string>
|
||||
<string name="start_date">Start date</string>
|
||||
<string name="timeline_description">Enable monitoring to collect movement data in the background.</string>
|
||||
<string name="send_location_as">Send location as</string>
|
||||
<string name="send_location_as_descr">Choose how messages with your location will look like.</string>
|
||||
<string name="shared_string_map">Map</string>
|
||||
|
@ -176,6 +185,7 @@
|
|||
<string name="welcome_descr"><![CDATA[<b>OsmAnd Location Sharing</b> lets you share your location and see that of others in the OsmAnd.<br/><br/>The app uses Telegram API and you need a Telegram account.]]></string>
|
||||
<string name="my_location">My location</string>
|
||||
<string name="live_now">Live now</string>
|
||||
<string name="timeline">Timeline</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
package net.osmand;
|
||||
|
||||
import android.util.Xml;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
public class PlatformUtil {
|
||||
|
||||
|
@ -143,4 +148,11 @@ public class PlatformUtil {
|
|||
return getLog(cl.getName());
|
||||
}
|
||||
|
||||
public static XmlPullParser newXMLPullParser() throws XmlPullParserException {
|
||||
return Xml.newPullParser();
|
||||
}
|
||||
|
||||
public static XmlSerializer newSerializer() {
|
||||
return Xml.newSerializer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package net.osmand.aidl;
|
||||
|
||||
import net.osmand.aidl.search.SearchResult;
|
||||
import net.osmand.aidl.gpx.AGpxBitmap;
|
||||
|
||||
interface IOsmAndAidlCallback {
|
||||
void onSearchComplete(in List<SearchResult> resultSet);
|
||||
|
||||
void onUpdate();
|
||||
|
||||
void onAppInitialized();
|
||||
|
||||
void onGpxBitmapCreated(in AGpxBitmap bitmap);
|
||||
}
|
|
@ -55,6 +55,9 @@ import net.osmand.aidl.maplayer.point.ShowMapPointParams;
|
|||
|
||||
import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams;
|
||||
|
||||
import net.osmand.aidl.navdrawer.NavDrawerFooterParams;
|
||||
import net.osmand.aidl.navdrawer.NavDrawerHeaderParams;
|
||||
|
||||
import net.osmand.aidl.navigation.PauseNavigationParams;
|
||||
import net.osmand.aidl.navigation.ResumeNavigationParams;
|
||||
import net.osmand.aidl.navigation.StopNavigationParams;
|
||||
|
@ -67,6 +70,16 @@ import net.osmand.aidl.search.SearchResult;
|
|||
import net.osmand.aidl.search.SearchParams;
|
||||
import net.osmand.aidl.navigation.NavigateSearchParams;
|
||||
|
||||
import net.osmand.aidl.customization.SetWidgetsParams;
|
||||
import net.osmand.aidl.customization.OsmandSettingsParams;
|
||||
|
||||
import net.osmand.aidl.gpx.AGpxFile;
|
||||
import net.osmand.aidl.gpx.AGpxFileDetails;
|
||||
import net.osmand.aidl.gpx.CreateGpxBitmapParams;
|
||||
import net.osmand.aidl.tiles.ASqliteDbFile;
|
||||
|
||||
import net.osmand.aidl.plugins.PluginParams;
|
||||
|
||||
// NOTE: Add new methods at the end of file!!!
|
||||
|
||||
interface IOsmAndAidlInterface {
|
||||
|
@ -133,4 +146,34 @@ interface IOsmAndAidlInterface {
|
|||
|
||||
long registerForUpdates(in long updateTimeMS, IOsmAndAidlCallback callback);
|
||||
boolean unregisterFromUpdates(in long callbackId);
|
||||
|
||||
boolean setNavDrawerLogo(in String imageUri);
|
||||
|
||||
boolean setEnabledIds(in List<String> ids);
|
||||
boolean setDisabledIds(in List<String> ids);
|
||||
boolean setEnabledPatterns(in List<String> patterns);
|
||||
boolean setDisabledPatterns(in List<String> patterns);
|
||||
|
||||
boolean regWidgetVisibility(in SetWidgetsParams params);
|
||||
boolean regWidgetAvailability(in SetWidgetsParams params);
|
||||
|
||||
boolean customizeOsmandSettings(in OsmandSettingsParams params);
|
||||
|
||||
boolean getImportedGpx(out List<AGpxFile> files);
|
||||
|
||||
boolean getSqliteDbFiles(out List<ASqliteDbFile> files);
|
||||
boolean getActiveSqliteDbFiles(out List<ASqliteDbFile> files);
|
||||
boolean showSqliteDbFile(String fileName);
|
||||
boolean hideSqliteDbFile(String fileName);
|
||||
|
||||
boolean setNavDrawerLogoWithParams(in NavDrawerHeaderParams params);
|
||||
boolean setNavDrawerFooterWithParams(in NavDrawerFooterParams params);
|
||||
|
||||
boolean restoreOsmand();
|
||||
|
||||
boolean changePluginState(in PluginParams params);
|
||||
|
||||
boolean registerForOsmandInitListener(in IOsmAndAidlCallback callback);
|
||||
|
||||
boolean getBitmapForGpx(in CreateGpxBitmapParams file, IOsmAndAidlCallback callback);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.customization;
|
||||
|
||||
parcelable OsmandSettingsParams;
|
|
@ -0,0 +1,60 @@
|
|||
package net.osmand.aidl.customization;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class OsmandSettingsParams implements Parcelable {
|
||||
|
||||
private String sharedPreferencesName;
|
||||
private Bundle bundle;
|
||||
|
||||
public OsmandSettingsParams(@NonNull String sharedPreferencesName, @Nullable Bundle bundle) {
|
||||
this.sharedPreferencesName = sharedPreferencesName;
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
public OsmandSettingsParams(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<OsmandSettingsParams> CREATOR = new Creator<OsmandSettingsParams>() {
|
||||
@Override
|
||||
public OsmandSettingsParams createFromParcel(Parcel in) {
|
||||
return new OsmandSettingsParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OsmandSettingsParams[] newArray(int size) {
|
||||
return new OsmandSettingsParams[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getSharedPreferencesName() {
|
||||
return sharedPreferencesName;
|
||||
}
|
||||
|
||||
public Bundle getBundle() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(sharedPreferencesName);
|
||||
out.writeBundle(bundle);
|
||||
}
|
||||
|
||||
@SuppressLint("ParcelClassLoader")
|
||||
private void readFromParcel(Parcel in) {
|
||||
sharedPreferencesName = in.readString();
|
||||
bundle = in.readBundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.customization;
|
||||
|
||||
parcelable SetWidgetsParams;
|
|
@ -0,0 +1,93 @@
|
|||
package net.osmand.aidl.customization;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SetWidgetsParams implements Parcelable {
|
||||
|
||||
private String widgetKey;
|
||||
private List<String> appModesKeys;
|
||||
|
||||
public SetWidgetsParams(String widgetKey, @Nullable List<String> appModesKeys) {
|
||||
this.widgetKey = widgetKey;
|
||||
this.appModesKeys = appModesKeys;
|
||||
}
|
||||
|
||||
public SetWidgetsParams(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<SetWidgetsParams> CREATOR = new Creator<SetWidgetsParams>() {
|
||||
@Override
|
||||
public SetWidgetsParams createFromParcel(Parcel in) {
|
||||
return new SetWidgetsParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetWidgetsParams[] newArray(int size) {
|
||||
return new SetWidgetsParams[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getWidgetKey() {
|
||||
return widgetKey;
|
||||
}
|
||||
|
||||
public List<String> getAppModesKeys() {
|
||||
return appModesKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(widgetKey);
|
||||
writeStringList(out, appModesKeys);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
widgetKey = in.readString();
|
||||
appModesKeys = readStringList(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void writeStringList(Parcel out, List<String> val) {
|
||||
if (val == null) {
|
||||
out.writeInt(-1);
|
||||
return;
|
||||
}
|
||||
int N = val.size();
|
||||
int i = 0;
|
||||
out.writeInt(N);
|
||||
while (i < N) {
|
||||
out.writeString(val.get(i));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> readStringList(Parcel in) {
|
||||
List<String> list = new ArrayList<>();
|
||||
int M = list.size();
|
||||
int N = in.readInt();
|
||||
if (N == -1) {
|
||||
return null;
|
||||
}
|
||||
int i = 0;
|
||||
for (; i < M && i < N; i++) {
|
||||
list.set(i, in.readString());
|
||||
}
|
||||
for (; i < N; i++) {
|
||||
list.add(in.readString());
|
||||
}
|
||||
for (; i < M; i++) {
|
||||
list.remove(N);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
4
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxBitmap.aidl
Normal file
|
@ -0,0 +1,4 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable AGpxBitmap;
|
||||
|
50
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxBitmap.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class AGpxBitmap implements Parcelable {
|
||||
|
||||
private Bitmap bitmap;
|
||||
|
||||
public AGpxBitmap(@NonNull Bitmap bitmap) {
|
||||
this.bitmap = bitmap;
|
||||
}
|
||||
|
||||
public AGpxBitmap(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public Bitmap getBitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public void setBitmap(Bitmap bitmap) {
|
||||
this.bitmap = bitmap;
|
||||
}
|
||||
|
||||
public static final Creator<AGpxBitmap> CREATOR = new
|
||||
Creator<AGpxBitmap>() {
|
||||
public AGpxBitmap createFromParcel(Parcel in) {
|
||||
return new AGpxBitmap(in);
|
||||
}
|
||||
|
||||
public AGpxBitmap[] newArray(int size) {
|
||||
return new AGpxBitmap[size];
|
||||
}
|
||||
};
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeParcelable(bitmap, flags);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
bitmap = in.readParcelable(Bitmap.class.getClassLoader());
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
3
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFile.aidl
Normal file
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable AGpxFile;
|
89
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFile.java
Normal file
|
@ -0,0 +1,89 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class AGpxFile implements Parcelable {
|
||||
|
||||
private String fileName;
|
||||
private long modifiedTime;
|
||||
private long fileSize;
|
||||
private boolean active;
|
||||
private AGpxFileDetails details;
|
||||
|
||||
public AGpxFile(@NonNull String fileName, long modifiedTime, long fileSize, boolean active, @Nullable AGpxFileDetails details) {
|
||||
this.fileName = fileName;
|
||||
this.modifiedTime = modifiedTime;
|
||||
this.fileSize = fileSize;
|
||||
this.active = active;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public AGpxFile(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<AGpxFile> CREATOR = new
|
||||
Creator<AGpxFile>() {
|
||||
public AGpxFile createFromParcel(Parcel in) {
|
||||
return new AGpxFile(in);
|
||||
}
|
||||
|
||||
public AGpxFile[] newArray(int size) {
|
||||
return new AGpxFile[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public long getModifiedTime() {
|
||||
return modifiedTime;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public AGpxFileDetails getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(fileName);
|
||||
out.writeLong(modifiedTime);
|
||||
out.writeLong(fileSize);
|
||||
out.writeByte((byte) (active ? 1 : 0));
|
||||
|
||||
out.writeByte((byte) (details != null ? 1 : 0));
|
||||
if (details != null) {
|
||||
out.writeParcelable(details, flags);
|
||||
}
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
fileName = in.readString();
|
||||
modifiedTime = in.readLong();
|
||||
fileSize = in.readLong();
|
||||
active = in.readByte() != 0;
|
||||
|
||||
boolean hasDetails= in.readByte() != 0;
|
||||
if (hasDetails) {
|
||||
details = in.readParcelable(AGpxFileDetails.class.getClassLoader());
|
||||
} else {
|
||||
details = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable AGpxFileDetails;
|
196
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFileDetails.java
Normal file
|
@ -0,0 +1,196 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AGpxFileDetails implements Parcelable {
|
||||
|
||||
private float totalDistance = 0;
|
||||
private int totalTracks = 0;
|
||||
private long startTime = Long.MAX_VALUE;
|
||||
private long endTime = Long.MIN_VALUE;
|
||||
private long timeSpan = 0;
|
||||
private long timeMoving = 0;
|
||||
private float totalDistanceMoving = 0;
|
||||
|
||||
private double diffElevationUp = 0;
|
||||
private double diffElevationDown = 0;
|
||||
private double avgElevation = 0;
|
||||
private double minElevation = 99999;
|
||||
private double maxElevation = -100;
|
||||
|
||||
private float minSpeed = Float.MAX_VALUE;
|
||||
private float maxSpeed = 0;
|
||||
private float avgSpeed;
|
||||
|
||||
private int points;
|
||||
private int wptPoints = 0;
|
||||
|
||||
private List<String> wptCategoryNames = new ArrayList<>();
|
||||
|
||||
public AGpxFileDetails(float totalDistance, int totalTracks,
|
||||
long startTime, long endTime,
|
||||
long timeSpan, long timeMoving, float totalDistanceMoving,
|
||||
double diffElevationUp, double diffElevationDown,
|
||||
double avgElevation, double minElevation, double maxElevation,
|
||||
float minSpeed, float maxSpeed, float avgSpeed,
|
||||
int points, int wptPoints, Set<String> wptCategoryNames) {
|
||||
this.totalDistance = totalDistance;
|
||||
this.totalTracks = totalTracks;
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
this.timeSpan = timeSpan;
|
||||
this.timeMoving = timeMoving;
|
||||
this.totalDistanceMoving = totalDistanceMoving;
|
||||
this.diffElevationUp = diffElevationUp;
|
||||
this.diffElevationDown = diffElevationDown;
|
||||
this.avgElevation = avgElevation;
|
||||
this.minElevation = minElevation;
|
||||
this.maxElevation = maxElevation;
|
||||
this.minSpeed = minSpeed;
|
||||
this.maxSpeed = maxSpeed;
|
||||
this.avgSpeed = avgSpeed;
|
||||
this.points = points;
|
||||
this.wptPoints = wptPoints;
|
||||
if (wptCategoryNames != null) {
|
||||
this.wptCategoryNames = new ArrayList<>(wptCategoryNames);
|
||||
}
|
||||
}
|
||||
|
||||
public AGpxFileDetails(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<AGpxFileDetails> CREATOR = new
|
||||
Creator<AGpxFileDetails>() {
|
||||
public AGpxFileDetails createFromParcel(Parcel in) {
|
||||
return new AGpxFileDetails(in);
|
||||
}
|
||||
|
||||
public AGpxFileDetails[] newArray(int size) {
|
||||
return new AGpxFileDetails[size];
|
||||
}
|
||||
};
|
||||
|
||||
public float getTotalDistance() {
|
||||
return totalDistance;
|
||||
}
|
||||
|
||||
public int getTotalTracks() {
|
||||
return totalTracks;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public long getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public long getTimeSpan() {
|
||||
return timeSpan;
|
||||
}
|
||||
|
||||
public long getTimeMoving() {
|
||||
return timeMoving;
|
||||
}
|
||||
|
||||
public float getTotalDistanceMoving() {
|
||||
return totalDistanceMoving;
|
||||
}
|
||||
|
||||
public double getDiffElevationUp() {
|
||||
return diffElevationUp;
|
||||
}
|
||||
|
||||
public double getDiffElevationDown() {
|
||||
return diffElevationDown;
|
||||
}
|
||||
|
||||
public double getAvgElevation() {
|
||||
return avgElevation;
|
||||
}
|
||||
|
||||
public double getMinElevation() {
|
||||
return minElevation;
|
||||
}
|
||||
|
||||
public double getMaxElevation() {
|
||||
return maxElevation;
|
||||
}
|
||||
|
||||
public float getMinSpeed() {
|
||||
return minSpeed;
|
||||
}
|
||||
|
||||
public float getMaxSpeed() {
|
||||
return maxSpeed;
|
||||
}
|
||||
|
||||
public float getAvgSpeed() {
|
||||
return avgSpeed;
|
||||
}
|
||||
|
||||
public int getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public int getWptPoints() {
|
||||
return wptPoints;
|
||||
}
|
||||
|
||||
public List<String> getWptCategoryNames() {
|
||||
return wptCategoryNames;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeFloat(totalDistance);
|
||||
out.writeInt(totalTracks);
|
||||
out.writeLong(startTime);
|
||||
out.writeLong(endTime);
|
||||
out.writeLong(timeSpan);
|
||||
out.writeLong(timeMoving);
|
||||
out.writeFloat(totalDistanceMoving);
|
||||
out.writeDouble(diffElevationUp);
|
||||
out.writeDouble(diffElevationDown);
|
||||
out.writeDouble(avgElevation);
|
||||
out.writeDouble(minElevation);
|
||||
out.writeDouble(maxElevation);
|
||||
out.writeFloat(minSpeed);
|
||||
out.writeFloat(maxSpeed);
|
||||
out.writeFloat(avgSpeed);
|
||||
out.writeInt(points);
|
||||
out.writeInt(wptPoints);
|
||||
out.writeStringList(wptCategoryNames);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
totalDistance = in.readFloat();
|
||||
totalTracks = in.readInt();
|
||||
startTime = in.readLong();
|
||||
endTime = in.readLong();
|
||||
timeSpan = in.readLong();
|
||||
timeMoving = in.readLong();
|
||||
totalDistanceMoving = in.readFloat();
|
||||
diffElevationUp = in.readDouble();
|
||||
diffElevationDown = in.readDouble();
|
||||
avgElevation = in.readDouble();
|
||||
minElevation = in.readDouble();
|
||||
maxElevation = in.readDouble();
|
||||
minSpeed = in.readFloat();
|
||||
maxSpeed = in.readFloat();
|
||||
avgSpeed = in.readFloat();
|
||||
points = in.readInt();
|
||||
wptPoints = in.readInt();
|
||||
in.readStringList(wptCategoryNames);
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable CreateGpxBitmapParams;
|
|
@ -0,0 +1,101 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CreateGpxBitmapParams implements Parcelable {
|
||||
|
||||
private File gpxFile;
|
||||
private Uri gpxUri;
|
||||
private float density;
|
||||
private int widthPixels;
|
||||
private int heightPixels;
|
||||
private int color; //ARGB color int
|
||||
|
||||
public CreateGpxBitmapParams(File gpxFile, float density, int widthPixels, int heightPixels, int color) {
|
||||
this.gpxFile = gpxFile;
|
||||
this.density = density;
|
||||
this.widthPixels = widthPixels;
|
||||
this.heightPixels = heightPixels;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams(Uri gpxUri, float density, int widthPixels, int heightPixels, int color) {
|
||||
this.gpxUri = gpxUri;
|
||||
this.density = density;
|
||||
this.widthPixels = widthPixels;
|
||||
this.heightPixels = heightPixels;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<CreateGpxBitmapParams> CREATOR = new
|
||||
Creator<CreateGpxBitmapParams>() {
|
||||
public CreateGpxBitmapParams createFromParcel(Parcel in) {
|
||||
return new CreateGpxBitmapParams(in);
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams[] newArray(int size) {
|
||||
return new CreateGpxBitmapParams[size];
|
||||
}
|
||||
};
|
||||
|
||||
public File getGpxFile() {
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
public Uri getGpxUri() {
|
||||
return gpxUri;
|
||||
}
|
||||
|
||||
public int getWidthPixels() {
|
||||
return widthPixels;
|
||||
}
|
||||
|
||||
public int getHeightPixels() {
|
||||
return heightPixels;
|
||||
}
|
||||
|
||||
public float getDensity() {
|
||||
return density;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
if (gpxFile != null) {
|
||||
out.writeString(gpxFile.getAbsolutePath());
|
||||
} else {
|
||||
out.writeString(null);
|
||||
}
|
||||
out.writeParcelable(gpxUri, flags);
|
||||
out.writeFloat(density);
|
||||
out.writeInt(widthPixels);
|
||||
out.writeInt(heightPixels);
|
||||
out.writeInt(color);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
String gpxAbsolutePath = in.readString();
|
||||
if (gpxAbsolutePath != null) {
|
||||
gpxFile = new File(gpxAbsolutePath);
|
||||
}
|
||||
gpxUri = in.readParcelable(Uri.class.getClassLoader());
|
||||
density = in.readFloat();
|
||||
widthPixels = in.readInt();
|
||||
heightPixels = in.readInt();
|
||||
color = in.readInt();
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.navdrawer;
|
||||
|
||||
parcelable NavDrawerFooterParams;
|
|
@ -0,0 +1,68 @@
|
|||
package net.osmand.aidl.navdrawer;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class NavDrawerFooterParams implements Parcelable {
|
||||
|
||||
@NonNull
|
||||
private String packageName;
|
||||
@Nullable
|
||||
private String intent;
|
||||
@Nullable
|
||||
private String appName;
|
||||
|
||||
@NonNull
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getIntent() {
|
||||
return intent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public NavDrawerFooterParams(@NonNull String packageName, @Nullable String intent,
|
||||
@Nullable String appName) {
|
||||
this.packageName = packageName;
|
||||
this.intent = intent;
|
||||
this.appName = appName;
|
||||
}
|
||||
|
||||
protected NavDrawerFooterParams(Parcel in) {
|
||||
packageName = in.readString();
|
||||
intent = in.readString();
|
||||
appName = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(packageName);
|
||||
dest.writeString(intent);
|
||||
dest.writeString(appName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<NavDrawerFooterParams> CREATOR = new Creator<NavDrawerFooterParams>() {
|
||||
@Override
|
||||
public NavDrawerFooterParams createFromParcel(Parcel in) {
|
||||
return new NavDrawerFooterParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavDrawerFooterParams[] newArray(int size) {
|
||||
return new NavDrawerFooterParams[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.navdrawer;
|
||||
|
||||
parcelable NavDrawerHeaderParams;
|
|
@ -0,0 +1,68 @@
|
|||
package net.osmand.aidl.navdrawer;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class NavDrawerHeaderParams implements Parcelable {
|
||||
|
||||
@NonNull
|
||||
private String imageUri;
|
||||
@NonNull
|
||||
private String packageName;
|
||||
@Nullable
|
||||
private String intent;
|
||||
|
||||
@NonNull
|
||||
public String getImageUri() {
|
||||
return imageUri;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getIntent() {
|
||||
return intent;
|
||||
}
|
||||
|
||||
public NavDrawerHeaderParams(@NonNull String imageUri, @NonNull String packageName,
|
||||
@Nullable String intent) {
|
||||
this.imageUri = imageUri;
|
||||
this.packageName = packageName;
|
||||
this.intent = intent;
|
||||
}
|
||||
|
||||
public NavDrawerHeaderParams(Parcel in) {
|
||||
imageUri = in.readString();
|
||||
packageName = in.readString();
|
||||
intent = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(imageUri);
|
||||
dest.writeString(packageName);
|
||||
dest.writeString(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<NavDrawerHeaderParams> CREATOR = new Creator<NavDrawerHeaderParams>() {
|
||||
@Override
|
||||
public NavDrawerHeaderParams createFromParcel(Parcel in) {
|
||||
return new NavDrawerHeaderParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavDrawerHeaderParams[] newArray(int size) {
|
||||
return new NavDrawerHeaderParams[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// PluginParams.aidl
|
||||
package net.osmand.aidl.plugins;
|
||||
|
||||
parcelable PluginParams;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package net.osmand.aidl.plugins;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class PluginParams implements Parcelable {
|
||||
|
||||
private String pluginId;
|
||||
private int newState; //0- off, 1 - on
|
||||
|
||||
public PluginParams(String pluginId, int newState) {
|
||||
this.pluginId = pluginId;
|
||||
this.newState = newState;
|
||||
}
|
||||
|
||||
public String getPluginId() {
|
||||
return pluginId;
|
||||
}
|
||||
|
||||
public int getNewState() {
|
||||
return newState;
|
||||
}
|
||||
|
||||
protected PluginParams(Parcel in) {
|
||||
pluginId = in.readString();
|
||||
newState = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(pluginId);
|
||||
dest.writeInt(newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<PluginParams> CREATOR = new Creator<PluginParams>() {
|
||||
@Override
|
||||
public PluginParams createFromParcel(Parcel in) {
|
||||
return new PluginParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginParams[] newArray(int size) {
|
||||
return new PluginParams[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.tiles;
|
||||
|
||||
parcelable ASqliteDbFile;
|
69
OsmAnd-telegram/src/net/osmand/aidl/tiles/ASqliteDbFile.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
package net.osmand.aidl.tiles;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class ASqliteDbFile implements Parcelable {
|
||||
|
||||
private String fileName;
|
||||
private long modifiedTime;
|
||||
private long fileSize;
|
||||
private boolean active;
|
||||
|
||||
public ASqliteDbFile(@NonNull String fileName, long modifiedTime, long fileSize, boolean active) {
|
||||
this.fileName = fileName;
|
||||
this.modifiedTime = modifiedTime;
|
||||
this.fileSize = fileSize;
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public ASqliteDbFile(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<ASqliteDbFile> CREATOR = new
|
||||
Creator<ASqliteDbFile>() {
|
||||
public ASqliteDbFile createFromParcel(Parcel in) {
|
||||
return new ASqliteDbFile(in);
|
||||
}
|
||||
|
||||
public ASqliteDbFile[] newArray(int size) {
|
||||
return new ASqliteDbFile[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public long getModifiedTime() {
|
||||
return modifiedTime;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(fileName);
|
||||
out.writeLong(modifiedTime);
|
||||
out.writeLong(fileSize);
|
||||
out.writeByte((byte) (active ? 1 : 0));
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
fileName = in.readString();
|
||||
modifiedTime = in.readLong();
|
||||
fileSize = in.readLong();
|
||||
active = in.readByte() != 0;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ class TelegramApplication : Application(), OsmandHelperListener {
|
|||
lateinit var osmandAidlHelper: OsmandAidlHelper private set
|
||||
lateinit var locationProvider: TelegramLocationProvider private set
|
||||
lateinit var messagesDbHelper: MessagesDbHelper private set
|
||||
lateinit var savingTracksDbHelper: SavingTracksDbHelper private set
|
||||
|
||||
var telegramService: TelegramService? = null
|
||||
|
||||
|
@ -68,6 +69,7 @@ class TelegramApplication : Application(), OsmandHelperListener {
|
|||
notificationHelper = NotificationHelper(this)
|
||||
locationProvider = TelegramLocationProvider(this)
|
||||
messagesDbHelper = MessagesDbHelper(this)
|
||||
savingTracksDbHelper = SavingTracksDbHelper(this)
|
||||
|
||||
if (settings.hasAnyChatToShareLocation() && AndroidUtils.isLocationPermissionAvailable(this)) {
|
||||
shareLocationHelper.startSharingLocation()
|
||||
|
|
|
@ -79,6 +79,8 @@ private const val SHARE_CHATS_INFO_KEY = "share_chats_info"
|
|||
|
||||
private const val BATTERY_OPTIMISATION_ASKED = "battery_optimisation_asked"
|
||||
|
||||
private const val MONITORING_ENABLED = "monitoring_enabled"
|
||||
|
||||
private const val SHARING_INITIALIZATION_TIME = 60 * 2L // 2 minutes
|
||||
|
||||
private const val GPS_UPDATE_EXPIRED_TIME = 60 * 3L // 3 minutes
|
||||
|
@ -105,12 +107,14 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
var appToConnectPackage = ""
|
||||
private set
|
||||
|
||||
var liveNowSortType = LiveNowSortType.SORT_BY_GROUP
|
||||
var liveNowSortType = LiveNowSortType.SORT_BY_DISTANCE
|
||||
|
||||
val gpsAndLocPrefs = listOf(SendMyLocPref(), StaleLocPref(), LocHistoryPref(), ShareTypePref())
|
||||
|
||||
var batteryOptimisationAsked = false
|
||||
|
||||
var monitoringEnabled = false
|
||||
|
||||
init {
|
||||
updatePrefs()
|
||||
read()
|
||||
|
@ -435,6 +439,8 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
edit.putBoolean(BATTERY_OPTIMISATION_ASKED, batteryOptimisationAsked)
|
||||
|
||||
edit.putBoolean(MONITORING_ENABLED, monitoringEnabled)
|
||||
|
||||
val jArray = convertShareChatsInfoToJson()
|
||||
if (jArray != null) {
|
||||
edit.putString(SHARE_CHATS_INFO_KEY, jArray.toString())
|
||||
|
@ -487,10 +493,12 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
appToConnectPackage = prefs.getString(APP_TO_CONNECT_PACKAGE_KEY, "")
|
||||
|
||||
liveNowSortType = LiveNowSortType.valueOf(
|
||||
prefs.getString(LIVE_NOW_SORT_TYPE_KEY, LiveNowSortType.SORT_BY_GROUP.name)
|
||||
prefs.getString(LIVE_NOW_SORT_TYPE_KEY, LiveNowSortType.SORT_BY_DISTANCE.name)
|
||||
)
|
||||
|
||||
batteryOptimisationAsked = prefs.getBoolean(BATTERY_OPTIMISATION_ASKED,false)
|
||||
|
||||
monitoringEnabled = prefs.getBoolean(MONITORING_ENABLED,false)
|
||||
}
|
||||
|
||||
private fun convertShareDevicesToJson():JSONObject?{
|
||||
|
|
|
@ -75,6 +75,12 @@ class OsmandAidlHelper(private val app: TelegramApplication) {
|
|||
fun onSearchComplete(resultSet: List<SearchResult>)
|
||||
}
|
||||
|
||||
private var gpxBitmapCreatedListener: GpxBitmapCreatedListener? = null
|
||||
|
||||
interface GpxBitmapCreatedListener {
|
||||
fun onGpxBitmapCreated(bitmap: AGpxBitmap)
|
||||
}
|
||||
|
||||
private val mIOsmAndAidlCallback = object : IOsmAndAidlCallback.Stub() {
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
|
@ -90,12 +96,26 @@ class OsmandAidlHelper(private val app: TelegramApplication) {
|
|||
mUpdatesListener!!.update()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAppInitialized() {
|
||||
|
||||
}
|
||||
|
||||
override fun onGpxBitmapCreated(bitmap: AGpxBitmap) {
|
||||
if (gpxBitmapCreatedListener != null) {
|
||||
gpxBitmapCreatedListener!!.onGpxBitmapCreated(bitmap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setSearchCompleteListener(mSearchCompleteListener: SearchCompleteListener) {
|
||||
this.mSearchCompleteListener = mSearchCompleteListener
|
||||
}
|
||||
|
||||
fun setGpxBitmapCreatedListener(gpxBitmapCreatedListener: GpxBitmapCreatedListener) {
|
||||
this.gpxBitmapCreatedListener = gpxBitmapCreatedListener
|
||||
}
|
||||
|
||||
private var mUpdatesListener: UpdatesListener? = null
|
||||
|
||||
interface UpdatesListener {
|
||||
|
@ -1059,4 +1079,16 @@ class OsmandAidlHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getBitmapForGpx(gpxUri: Uri, density: Float, widthPixels: Int, heightPixels: Int, color: Int): Boolean {
|
||||
if (mIOsmAndAidlInterface != null) {
|
||||
try {
|
||||
app.grantUriPermission(app.settings.appToConnectPackage, gpxUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
return mIOsmAndAidlInterface!!.getBitmapForGpx(CreateGpxBitmapParams(gpxUri, density, widthPixels, heightPixels, color), mIOsmAndAidlCallback)
|
||||
} catch (e: RemoteException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,476 @@
|
|||
package net.osmand.telegram.helpers;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.telegram.TelegramApplication;
|
||||
import net.osmand.telegram.utils.GPXUtilities;
|
||||
import net.osmand.telegram.utils.GPXUtilities.GPXFile;
|
||||
import net.osmand.telegram.utils.GPXUtilities.Track;
|
||||
import net.osmand.telegram.utils.GPXUtilities.TrkSegment;
|
||||
import net.osmand.telegram.utils.GPXUtilities.WptPt;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.drinkless.td.libcore.telegram.TdApi;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
||||
|
||||
private final static String DATABASE_NAME = "tracks";
|
||||
private final static int DATABASE_VERSION = 3;
|
||||
|
||||
private final static String TRACK_NAME = "track"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_USER_ID = "user_id"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_CHAT_ID = "chat_id"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_DATE = "date"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_LAT = "lat"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_LON = "lon"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_ALTITUDE = "altitude"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_SPEED = "speed"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_HDOP = "hdop"; //$NON-NLS-1$
|
||||
private final static String TRACK_COL_TEXT_INFO = "text_info"; // 1 = true, 0 = false //$NON-NLS-1$
|
||||
|
||||
private final static String INSERT_SCRIPT = "INSERT INTO " + TRACK_NAME + " (" + TRACK_COL_USER_ID + ", " + TRACK_COL_CHAT_ID + ", " + TRACK_COL_LAT + ", " + TRACK_COL_LON + ", "
|
||||
+ TRACK_COL_ALTITUDE + ", " + TRACK_COL_SPEED + ", " + TRACK_COL_HDOP + ", " + TRACK_COL_DATE + ", " + TRACK_COL_TEXT_INFO + ")"
|
||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private final static String CREATE_SCRIPT = "CREATE TABLE " + TRACK_NAME + " (" + TRACK_COL_USER_ID + " long," + TRACK_COL_CHAT_ID + " long," + TRACK_COL_LAT + " double, " + TRACK_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$//$NON-NLS-5$
|
||||
+ TRACK_COL_ALTITUDE + " double, " + TRACK_COL_SPEED + " double, " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ TRACK_COL_HDOP + " double, " + TRACK_COL_DATE + " long, " + TRACK_COL_TEXT_INFO + " int )";
|
||||
|
||||
private final static Log log = PlatformUtil.getLog(SavingTracksDbHelper.class);
|
||||
|
||||
private final TelegramApplication app;
|
||||
|
||||
public SavingTracksDbHelper(TelegramApplication app) {
|
||||
super(app, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
this.app = app;
|
||||
|
||||
app.getTelegramHelper().addIncomingMessagesListener(new TelegramHelper.TelegramIncomingMessagesListener() {
|
||||
|
||||
@Override
|
||||
public void onReceiveChatLocationMessages(long chatId, @NotNull TdApi.Message... messages) {
|
||||
for (TdApi.Message message : messages) {
|
||||
updateLocationMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleteChatLocationMessages(long chatId, @NotNull List<? extends TdApi.Message> messages) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLocationMessages() {
|
||||
|
||||
}
|
||||
});
|
||||
app.getTelegramHelper().addOutgoingMessagesListener(new TelegramHelper.TelegramOutgoingMessagesListener() {
|
||||
|
||||
@Override
|
||||
public void onUpdateMessages(@NotNull List<? extends TdApi.Message> messages) {
|
||||
for (TdApi.Message message : messages) {
|
||||
updateLocationMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleteMessages(long chatId, @NotNull List<Long> messages) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendLiveLocationError(int code, @NotNull String message) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(CREATE_SCRIPT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion < 3) {
|
||||
db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_TEXT_INFO + " int");
|
||||
}
|
||||
}
|
||||
|
||||
public void saveUserDataToGpx(SaveGpxListener listener, File dir, int userId, long chatId, long start, long end) {
|
||||
GPXFile gpxFile = collectRecordedDataForUserAndChat(userId, chatId, start, end);
|
||||
if (gpxFile != null && !gpxFile.isEmpty()) {
|
||||
SaveGPXTrackToFileTask task = new SaveGPXTrackToFileTask(app, listener, gpxFile, dir, userId);
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveGpx(SaveGpxListener listener, File dir, GPXFile gpxFile) {
|
||||
if (gpxFile != null && !gpxFile.isEmpty()) {
|
||||
SaveGPXTrackToFileTask task = new SaveGPXTrackToFileTask(app, listener, gpxFile, dir, 0);
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLocationMessage(TdApi.Message message) {
|
||||
log.debug(message);
|
||||
TdApi.MessageContent content = message.content;
|
||||
int senderId = app.getTelegramHelper().getSenderMessageId(message);
|
||||
if (content instanceof TdApi.MessageLocation) {
|
||||
long lastTextMessageUpdate = getLastTextTrackPointTimeForUser(message.senderUserId);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (lastTextMessageUpdate == 0 || currentTime - lastTextMessageUpdate < 10 * 1000) {
|
||||
log.debug("Add map message " + message.senderUserId);
|
||||
TdApi.MessageLocation messageLocation = (TdApi.MessageLocation) content;
|
||||
insertData(senderId, message.chatId, messageLocation.location.latitude,
|
||||
messageLocation.location.longitude, 0.0, 0.0, 0.0,
|
||||
Math.max(message.date, message.editDate), 0);
|
||||
} else {
|
||||
log.debug("Skip map message");
|
||||
}
|
||||
} else if (content instanceof TelegramHelper.MessageLocation) {
|
||||
log.debug("Add text message " + message.senderUserId);
|
||||
TelegramHelper.MessageLocation messageLocation = (TelegramHelper.MessageLocation) content;
|
||||
insertData(senderId, message.chatId, messageLocation.getLat(), messageLocation.getLon(),
|
||||
messageLocation.getAltitude(), messageLocation.getSpeed(), messageLocation.getHdop(),
|
||||
messageLocation.getLastUpdated() * 1000L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertData(int userId, long chatId, double lat, double lon, double alt, double speed, double hdop, long time, int textMessage) {
|
||||
execWithClose(INSERT_SCRIPT, new Object[]{userId, chatId, lat, lon, alt, speed, hdop, time, textMessage});
|
||||
}
|
||||
|
||||
private synchronized void execWithClose(String script, Object[] objects) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
try {
|
||||
if (db != null) {
|
||||
db.execSQL(script, objects);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} finally {
|
||||
if (db != null) {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long getLastTextTrackPointTimeForUser(int userId) {
|
||||
long res = 0;
|
||||
try {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
if (db != null) {
|
||||
try {
|
||||
Cursor query = db.rawQuery("SELECT " + TRACK_COL_DATE + " FROM " + TRACK_NAME + " WHERE " + TRACK_COL_USER_ID + " = ? AND "
|
||||
+ TRACK_COL_TEXT_INFO + " = ?" + " ORDER BY " + TRACK_COL_DATE + " ASC ", new String[]{String.valueOf(userId), String.valueOf(1)});
|
||||
if (query.moveToFirst()) {
|
||||
res = query.getLong(0);
|
||||
}
|
||||
query.close();
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public GPXFile collectRecordedDataForUserAndChat(int userId, long chatId, long start, long end) {
|
||||
GPXFile gpxFile = null;
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
if (db != null && db.isOpen()) {
|
||||
try {
|
||||
gpxFile = collectDBTracksForUser(db, userId, chatId, start, end);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
public GPXFile collectRecordedDataForUser(int userId, long chatId, long start, long end) {
|
||||
GPXFile gpxFile = null;
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
if (db != null && db.isOpen()) {
|
||||
try {
|
||||
if (chatId == 0) {
|
||||
gpxFile = collectDBTracksForUser(db, userId, start, end);
|
||||
} else {
|
||||
gpxFile = collectDBTracksForUser(db, userId, chatId, start, end);
|
||||
}
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
public ArrayList<GPXFile> collectRecordedDataForUsers(long start, long end, ArrayList<Integer> ignoredUsersIds) {
|
||||
ArrayList<GPXFile> data = new ArrayList<>();
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
if (db != null && db.isOpen()) {
|
||||
try {
|
||||
collectDBTracksForUsers(db, data, start, end, ignoredUsersIds);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private GPXFile collectDBTracksForUser(SQLiteDatabase db, int userId, long chatId, long start, long end) {
|
||||
Cursor query = db.rawQuery("SELECT " + TRACK_COL_USER_ID + "," + TRACK_COL_CHAT_ID + ","
|
||||
+ TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," + TRACK_COL_SPEED + ","
|
||||
+ TRACK_COL_HDOP + "," + TRACK_COL_DATE + " FROM " + TRACK_NAME + " WHERE " + TRACK_COL_USER_ID + " = ?"
|
||||
+ " AND " + TRACK_COL_CHAT_ID + " = ?" + " AND " + TRACK_COL_DATE + " BETWEEN " + start + " AND " + end
|
||||
+ " ORDER BY " + TRACK_COL_DATE + " ASC ", new String[]{String.valueOf(userId), String.valueOf(chatId)});
|
||||
|
||||
GPXFile gpxFile = null;
|
||||
long previousTime = 0;
|
||||
TrkSegment segment = null;
|
||||
Track track = null;
|
||||
if (query.moveToFirst()) {
|
||||
gpxFile = new GPXFile();
|
||||
gpxFile.chatId = chatId;
|
||||
gpxFile.userId = userId;
|
||||
do {
|
||||
long time = query.getLong(7);
|
||||
WptPt pt = new WptPt();
|
||||
pt.userId = query.getInt(0);
|
||||
pt.chatId = query.getLong(1);
|
||||
pt.lat = query.getDouble(2);
|
||||
pt.lon = query.getDouble(3);
|
||||
pt.ele = query.getDouble(4);
|
||||
pt.speed = query.getDouble(5);
|
||||
pt.hdop = query.getDouble(6);
|
||||
pt.time = time;
|
||||
long currentInterval = Math.abs(time - previousTime);
|
||||
|
||||
if (track != null) {
|
||||
if (currentInterval < 30 * 60 * 1000) {
|
||||
// 30 minute - same segment
|
||||
segment.points.add(pt);
|
||||
} else {
|
||||
segment = new TrkSegment();
|
||||
segment.points.add(pt);
|
||||
track.segments.add(segment);
|
||||
}
|
||||
} else {
|
||||
track = new Track();
|
||||
segment = new TrkSegment();
|
||||
track.segments.add(segment);
|
||||
segment.points.add(pt);
|
||||
|
||||
gpxFile.tracks.add(track);
|
||||
}
|
||||
previousTime = time;
|
||||
} while (query.moveToNext());
|
||||
}
|
||||
query.close();
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
private GPXFile collectDBTracksForUser(SQLiteDatabase db, int userId, long start, long end) {
|
||||
Cursor query = db.rawQuery("SELECT " + TRACK_COL_USER_ID + "," + TRACK_COL_CHAT_ID + ","
|
||||
+ TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," + TRACK_COL_SPEED + ","
|
||||
+ TRACK_COL_HDOP + "," + TRACK_COL_DATE + " FROM " + TRACK_NAME + " WHERE " + TRACK_COL_USER_ID + " = ?"
|
||||
+ " AND " + TRACK_COL_DATE + " BETWEEN " + start + " AND " + end
|
||||
+ " ORDER BY " + TRACK_COL_DATE + " ASC ", new String[]{String.valueOf(userId)});
|
||||
|
||||
GPXFile gpxFile = null;
|
||||
long previousTime = 0;
|
||||
TrkSegment segment = null;
|
||||
Track track = null;
|
||||
if (query.moveToFirst()) {
|
||||
gpxFile = new GPXFile();
|
||||
gpxFile.userId = userId;
|
||||
do {
|
||||
long time = query.getLong(7);
|
||||
WptPt pt = new WptPt();
|
||||
pt.userId = query.getInt(0);
|
||||
pt.chatId = query.getLong(1);
|
||||
pt.lat = query.getDouble(2);
|
||||
pt.lon = query.getDouble(3);
|
||||
pt.ele = query.getDouble(4);
|
||||
pt.speed = query.getDouble(5);
|
||||
pt.hdop = query.getDouble(6);
|
||||
pt.time = time;
|
||||
long currentInterval = Math.abs(time - previousTime);
|
||||
|
||||
if (track != null) {
|
||||
if (currentInterval < 30 * 60 * 1000) {
|
||||
// 30 minute - same segment
|
||||
segment.points.add(pt);
|
||||
} else {
|
||||
segment = new TrkSegment();
|
||||
segment.points.add(pt);
|
||||
track.segments.add(segment);
|
||||
}
|
||||
} else {
|
||||
track = new Track();
|
||||
segment = new TrkSegment();
|
||||
track.segments.add(segment);
|
||||
segment.points.add(pt);
|
||||
|
||||
gpxFile.tracks.add(track);
|
||||
}
|
||||
previousTime = time;
|
||||
} while (query.moveToNext());
|
||||
}
|
||||
query.close();
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
private void collectDBTracksForUsers(SQLiteDatabase db, ArrayList<GPXFile> dataTracks, long start, long end, ArrayList<Integer> ignoredUsersIds) {
|
||||
Cursor query = db.rawQuery("SELECT " + TRACK_COL_USER_ID + "," + TRACK_COL_CHAT_ID + ","
|
||||
+ TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," + TRACK_COL_SPEED + ","
|
||||
+ TRACK_COL_HDOP + "," + TRACK_COL_DATE + " FROM " + TRACK_NAME + " WHERE " + TRACK_COL_DATE
|
||||
+ " BETWEEN " + start + " AND " + end + " ORDER BY " + TRACK_COL_USER_ID + " ASC, "
|
||||
+ TRACK_COL_CHAT_ID + " ASC, " + TRACK_COL_DATE + " ASC ", null);
|
||||
|
||||
long previousTime = 0;
|
||||
long previousChatId = 0;
|
||||
int previousUserId = 0;
|
||||
TrkSegment segment = null;
|
||||
Track track = null;
|
||||
GPXFile gpx = new GPXFile();
|
||||
if (query.moveToFirst()) {
|
||||
do {
|
||||
int userId = query.getInt(0);
|
||||
if (ignoredUsersIds.contains(userId)) {
|
||||
continue;
|
||||
}
|
||||
int chatId = query.getInt(1);
|
||||
long time = query.getLong(7);
|
||||
if (previousUserId != userId || previousChatId != chatId) {
|
||||
gpx = new GPXFile();
|
||||
gpx.chatId = chatId;
|
||||
gpx.userId = userId;
|
||||
previousTime = 0;
|
||||
track = null;
|
||||
segment = null;
|
||||
dataTracks.add(gpx);
|
||||
}
|
||||
|
||||
WptPt pt = new WptPt();
|
||||
pt.userId = userId;
|
||||
pt.chatId = chatId;
|
||||
pt.lat = query.getDouble(2);
|
||||
pt.lon = query.getDouble(3);
|
||||
pt.ele = query.getDouble(4);
|
||||
pt.speed = query.getDouble(5);
|
||||
pt.hdop = query.getDouble(6);
|
||||
pt.time = time;
|
||||
long currentInterval = Math.abs(time - previousTime);
|
||||
if (track != null) {
|
||||
if (currentInterval < 30 * 60 * 1000) {
|
||||
// 30 minute - same segment
|
||||
segment.points.add(pt);
|
||||
} else {
|
||||
segment = new TrkSegment();
|
||||
segment.points.add(pt);
|
||||
track.segments.add(segment);
|
||||
}
|
||||
} else {
|
||||
track = new Track();
|
||||
segment = new TrkSegment();
|
||||
track.segments.add(segment);
|
||||
segment.points.add(pt);
|
||||
|
||||
gpx.tracks.add(track);
|
||||
}
|
||||
previousTime = time;
|
||||
previousUserId = userId;
|
||||
previousChatId = chatId;
|
||||
} while (query.moveToNext());
|
||||
}
|
||||
query.close();
|
||||
}
|
||||
|
||||
private static class SaveGPXTrackToFileTask extends AsyncTask<Void, Void, List<String>> {
|
||||
|
||||
private TelegramApplication app;
|
||||
private SaveGpxListener listener;
|
||||
|
||||
private final GPXFile gpxFile;
|
||||
private File dir;
|
||||
private int userId;
|
||||
|
||||
SaveGPXTrackToFileTask(TelegramApplication app, SaveGpxListener listener, GPXFile gpxFile, File dir, int userId) {
|
||||
this.gpxFile = gpxFile;
|
||||
this.listener = listener;
|
||||
this.app = app;
|
||||
this.dir = dir;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> doInBackground(Void... params) {
|
||||
List<String> warnings = new ArrayList<String>();
|
||||
dir.mkdirs();
|
||||
if (dir.getParentFile().canWrite()) {
|
||||
if (dir.exists()) {
|
||||
|
||||
// save file
|
||||
File fout = new File(dir, userId + ".gpx"); //$NON-NLS-1$
|
||||
if (!gpxFile.isEmpty()) {
|
||||
WptPt pt = gpxFile.findPointToShow();
|
||||
|
||||
TdApi.User user = app.getTelegramHelper().getUser(pt.userId);
|
||||
String fileName;
|
||||
if (user != null) {
|
||||
fileName = TelegramUiHelper.INSTANCE.getUserName(user)
|
||||
+ "_" + new SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(new Date(pt.time)); //$NON-NLS-1$
|
||||
} else {
|
||||
fileName = userId + "_" + new SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(new Date(pt.time)); //$NON-NLS-1$
|
||||
}
|
||||
fout = new File(dir, fileName + ".gpx"); //$NON-NLS-1$
|
||||
int ind = 1;
|
||||
while (fout.exists()) {
|
||||
fout = new File(dir, fileName + "_" + (++ind) + ".gpx"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
String warn = GPXUtilities.writeGpxFile(fout, gpxFile, app);
|
||||
if (warn != null) {
|
||||
warnings.add(warn);
|
||||
return warnings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<String> warnings) {
|
||||
if (listener != null) {
|
||||
if (warnings != null && warnings.isEmpty()) {
|
||||
listener.onSavingGpxFinish(gpxFile.path);
|
||||
} else {
|
||||
listener.onSavingGpxError(warnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface SaveGpxListener {
|
||||
|
||||
void onSavingGpxFinish(String path);
|
||||
|
||||
void onSavingGpxError(List<String> warnings);
|
||||
}
|
||||
}
|
|
@ -66,6 +66,8 @@ class TelegramHelper private constructor() {
|
|||
const val MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC = 61
|
||||
const val MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC = 60 * 60 * 24 - 1 // one day
|
||||
|
||||
const val MAX_LOCATION_MESSAGE_HISTORY_SCAN_SEC = 60 * 60 * 24 // one day
|
||||
|
||||
const val SEND_NEW_MESSAGE_INTERVAL_SEC = 10 * 60 // 10 minutes
|
||||
|
||||
private var helper: TelegramHelper? = null
|
||||
|
@ -389,6 +391,15 @@ class TelegramHelper private constructor() {
|
|||
|
||||
fun isBot(userId: Int) = users[userId]?.type is TdApi.UserTypeBot
|
||||
|
||||
fun getSenderMessageId(message: TdApi.Message): Int {
|
||||
val forwardInfo = message.forwardInfo
|
||||
return if (forwardInfo != null && forwardInfo is TdApi.MessageForwardedFromUser) {
|
||||
forwardInfo.senderUserId
|
||||
} else {
|
||||
message.senderUserId
|
||||
}
|
||||
}
|
||||
|
||||
fun startLiveMessagesUpdates(interval: Long) {
|
||||
stopLiveMessagesUpdates()
|
||||
|
||||
|
@ -450,7 +461,7 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun requestChats(reload: Boolean = false) {
|
||||
private fun requestChats(reload: Boolean = false, onComplete: (() -> Unit)?) {
|
||||
synchronized(chatList) {
|
||||
if (reload) {
|
||||
chatList.clear()
|
||||
|
@ -481,7 +492,8 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
}
|
||||
// chats had already been received through updates, let's retry request
|
||||
requestChats()
|
||||
requestChats(false, this@TelegramHelper::scanChatsHistory)
|
||||
onComplete?.invoke()
|
||||
}
|
||||
else -> listener?.onTelegramError(-1, "Receive wrong response from TDLib: $obj")
|
||||
}
|
||||
|
@ -615,6 +627,49 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
}
|
||||
|
||||
fun scanChatsHistory() {
|
||||
log.debug("scanChatsHistory: chatList: ${chatList.size}")
|
||||
chatList.forEach {
|
||||
scanChatHistory(it.chatId, 0, 0, 100)
|
||||
}
|
||||
}
|
||||
|
||||
private fun scanChatHistory(
|
||||
chatId: Long,
|
||||
fromMessageId: Long,
|
||||
offset: Int,
|
||||
limit: Int,
|
||||
onlyLocal: Boolean = false
|
||||
) {
|
||||
client?.send(TdApi.GetChatHistory(chatId, fromMessageId, offset, limit, onlyLocal)) { obj ->
|
||||
when (obj.constructor) {
|
||||
TdApi.Error.CONSTRUCTOR -> {
|
||||
val error = obj as TdApi.Error
|
||||
if (error.code != IGNORED_ERROR_CODE) {
|
||||
listener?.onTelegramError(error.code, error.message)
|
||||
}
|
||||
}
|
||||
TdApi.Messages.CONSTRUCTOR -> {
|
||||
val messages = (obj as TdApi.Messages).messages
|
||||
log.debug("scanChatHistory: chatId: $chatId fromMessageId: $fromMessageId size: ${messages.size}")
|
||||
if (messages.isNotEmpty()) {
|
||||
messages.forEach {
|
||||
addNewMessage(it)
|
||||
}
|
||||
val lastMessage = messages.last()
|
||||
val currentTime = System.currentTimeMillis() / 1000
|
||||
if (currentTime-Math.max(lastMessage.date, lastMessage.editDate) < MAX_LOCATION_MESSAGE_HISTORY_SCAN_SEC) {
|
||||
scanChatHistory(chatId, lastMessage.id, 0, 100)
|
||||
log.debug("scanChatHistory searchMessageId: ${lastMessage.id}")
|
||||
} else {
|
||||
log.debug("scanChatHistory finishForChat: $chatId")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestUser(id: Int) {
|
||||
client?.send(TdApi.GetUser(id)) { obj ->
|
||||
when (obj.constructor) {
|
||||
|
@ -671,8 +726,9 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
|
||||
private fun addNewMessage(message: TdApi.Message) {
|
||||
lastTelegramUpdateTime = Math.max(message.date, message.editDate)
|
||||
lastTelegramUpdateTime = Math.max(lastTelegramUpdateTime, Math.max(message.date, message.editDate))
|
||||
if (message.isAppropriate()) {
|
||||
log.debug("addNewMessage: $message")
|
||||
val fromBot = isOsmAndBot(message.senderUserId)
|
||||
val viaBot = isOsmAndBot(message.viaBotUserId)
|
||||
val oldContent = message.content
|
||||
|
@ -685,20 +741,32 @@ class TelegramHelper private constructor() {
|
|||
} else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) {
|
||||
message.content = parseOsmAndBotLocation(message)
|
||||
}
|
||||
if (message.isOutgoing) {
|
||||
outgoingMessagesListeners.forEach {
|
||||
it.onUpdateMessages(listOf(message))
|
||||
}
|
||||
} else {
|
||||
removeOldMessages(message, fromBot, viaBot)
|
||||
val oldMessage = usersLocationMessages.values.firstOrNull { getSenderMessageId(it) == getSenderMessageId(message) && !fromBot && !viaBot }
|
||||
val hasNewerMessage = oldMessage != null && (Math.max(message.editDate, message.date) < Math.max(oldMessage.editDate, oldMessage.date))
|
||||
if (!hasNewerMessage) {
|
||||
usersLocationMessages[message.id] = message
|
||||
}
|
||||
incomingMessagesListeners.forEach {
|
||||
if (!hasNewerMessage || it is SavingTracksDbHelper) {
|
||||
it.onReceiveChatLocationMessages(message.chatId, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeOldMessages(newMessage: TdApi.Message, fromBot: Boolean, viaBot: Boolean) {
|
||||
val iterator = usersLocationMessages.entries.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val message = iterator.next().value
|
||||
if (newMessage.chatId == message.chatId) {
|
||||
val sameSender = newMessage.senderUserId == message.senderUserId
|
||||
val sameSender = getSenderMessageId(newMessage) == getSenderMessageId(message)
|
||||
val viaSameBot = newMessage.viaBotUserId == message.viaBotUserId
|
||||
if (fromBot || viaBot) {
|
||||
if ((fromBot && sameSender) || (viaBot && viaSameBot)) {
|
||||
|
@ -710,7 +778,8 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (sameSender && isUserLocationMessage(message) && isUserLocationMessage(newMessage)) {
|
||||
} else if (sameSender && isUserLocationMessage(message) && isUserLocationMessage(newMessage)
|
||||
&& Math.max(newMessage.editDate, newMessage.date) > Math.max(message.editDate, message.date)) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
|
@ -1018,23 +1087,6 @@ class TelegramHelper private constructor() {
|
|||
return TdApi.InputMessageText(TdApi.FormattedText(textMessage, entities.toTypedArray()), true, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* @chatId Id of the chat
|
||||
* @message Text of the message
|
||||
*/
|
||||
fun sendTextMessage(chatId: Long, message: String): Boolean {
|
||||
// initialize reply markup just for testing
|
||||
//val row = arrayOf(TdApi.InlineKeyboardButton("https://telegram.org?1", TdApi.InlineKeyboardButtonTypeUrl()), TdApi.InlineKeyboardButton("https://telegram.org?2", TdApi.InlineKeyboardButtonTypeUrl()), TdApi.InlineKeyboardButton("https://telegram.org?3", TdApi.InlineKeyboardButtonTypeUrl()))
|
||||
//val replyMarkup = TdApi.ReplyMarkupInlineKeyboard(arrayOf(row, row, row))
|
||||
|
||||
if (haveAuthorization) {
|
||||
val content = TdApi.InputMessageText(TdApi.FormattedText(message, null), false, true)
|
||||
client?.send(TdApi.SendMessage(chatId, 0, false, true, null, content), defaultHandler)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun logout(): Boolean {
|
||||
return if (libraryLoaded) {
|
||||
haveAuthorization = false
|
||||
|
@ -1132,7 +1184,7 @@ class TelegramHelper private constructor() {
|
|||
if (wasAuthorized != haveAuthorization) {
|
||||
needRefreshActiveLiveLocationMessages = true
|
||||
if (haveAuthorization) {
|
||||
requestChats(true)
|
||||
requestChats(true, null)
|
||||
requestCurrentUser()
|
||||
requestContacts()
|
||||
}
|
||||
|
@ -1145,19 +1197,20 @@ class TelegramHelper private constructor() {
|
|||
if (isChannelPost) {
|
||||
return false
|
||||
}
|
||||
val content = content
|
||||
val isUserTextLocation = (content is TdApi.MessageText) && content.text.text.startsWith(USER_TEXT_LOCATION_TITLE)
|
||||
val isOsmAndBot = isOsmAndBot(senderUserId) || isOsmAndBot(viaBotUserId)
|
||||
if (isOutgoing && !isOsmAndBot) {
|
||||
if (!(isUserTextLocation || content is TdApi.MessageLocation || isOsmAndBot)) {
|
||||
return false
|
||||
}
|
||||
val lastEdited = Math.max(date, editDate)
|
||||
if (TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) - lastEdited > messageActiveTimeSec) {
|
||||
return false
|
||||
}
|
||||
val content = content
|
||||
val isUserTextLocation = (content is TdApi.MessageText) && content.text.text.startsWith(USER_TEXT_LOCATION_TITLE)
|
||||
|
||||
return when (content) {
|
||||
is TdApi.MessageLocation -> true
|
||||
is TdApi.MessageText -> (isOsmAndBot) && content.text.text.startsWith(DEVICE_PREFIX) || (isUserTextLocation && senderUserId != currentUser?.id)
|
||||
is TdApi.MessageText -> (isOsmAndBot) && content.text.text.startsWith(DEVICE_PREFIX) || isUserTextLocation
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
@ -1234,6 +1287,33 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
}
|
||||
}
|
||||
s.startsWith(ALTITUDE_PREFIX) -> {
|
||||
val altStr = s.removePrefix(ALTITUDE_PREFIX)
|
||||
try {
|
||||
val alt = altStr.split(" ").first()
|
||||
res.altitude = alt.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
s.startsWith(SPEED_PREFIX) -> {
|
||||
val altStr = s.removePrefix(SPEED_PREFIX)
|
||||
try {
|
||||
val alt = altStr.split(" ").first()
|
||||
res.speed = alt.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
s.startsWith(HDOP_PREFIX) -> {
|
||||
val altStr = s.removePrefix(HDOP_PREFIX)
|
||||
try {
|
||||
val alt = altStr.split(" ").first()
|
||||
res.hdop = alt.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
s.startsWith(UPDATED_PREFIX) -> {
|
||||
if (res.lastUpdated == 0) {
|
||||
val updatedStr = s.removePrefix(UPDATED_PREFIX)
|
||||
|
@ -1291,6 +1371,12 @@ class TelegramHelper private constructor() {
|
|||
internal set
|
||||
var lastUpdated: Int = 0
|
||||
internal set
|
||||
var speed: Double = 0.0
|
||||
internal set
|
||||
var altitude: Double = 0.0
|
||||
internal set
|
||||
var hdop: Double = 0.0
|
||||
internal set
|
||||
|
||||
override fun getConstructor() = -1
|
||||
|
||||
|
@ -1510,7 +1596,7 @@ class TelegramHelper private constructor() {
|
|||
lastTelegramUpdateTime = Math.max(message.date, message.editDate)
|
||||
}
|
||||
incomingMessagesListeners.forEach {
|
||||
it.onReceiveChatLocationMessages(message.chatId, message)
|
||||
it.updateLocationMessages()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1536,6 +1622,7 @@ class TelegramHelper private constructor() {
|
|||
newContent
|
||||
}
|
||||
}
|
||||
log.debug("UpdateMessageContent " + message.senderUserId)
|
||||
incomingMessagesListeners.forEach {
|
||||
it.onReceiveChatLocationMessages(message.chatId, message)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import net.osmand.telegram.R
|
|||
import net.osmand.telegram.TelegramApplication
|
||||
import net.osmand.telegram.helpers.TelegramHelper.MessageOsmAndBotLocation
|
||||
import net.osmand.telegram.helpers.TelegramHelper.MessageUserTextLocation
|
||||
import net.osmand.telegram.utils.GPXUtilities
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
|
||||
object TelegramUiHelper {
|
||||
|
@ -129,6 +130,10 @@ object TelegramUiHelper {
|
|||
}
|
||||
}
|
||||
|
||||
fun gpxToChatItem(helper: TelegramHelper, gpx: GPXUtilities.GPXFile, simpleUserItem: Boolean): GpxChatItem? {
|
||||
return if (simpleUserItem) gpxToUserGpxChatItem(helper, gpx) else gpxToGpxChatItem(helper, gpx)
|
||||
}
|
||||
|
||||
private fun botMessageToLocationItem(
|
||||
chat: TdApi.Chat,
|
||||
content: MessageOsmAndBotLocation
|
||||
|
@ -224,6 +229,49 @@ object TelegramUiHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private fun gpxToGpxChatItem(
|
||||
helper: TelegramHelper,
|
||||
gpx: GPXUtilities.GPXFile
|
||||
): GpxChatItem? {
|
||||
val user = helper.getUser(gpx.userId) ?: return null
|
||||
val chat = helper.getChat(gpx.chatId) ?: return null
|
||||
return GpxChatItem().apply {
|
||||
chatId = chat.id
|
||||
chatTitle = chat.title
|
||||
gpxFile = gpx
|
||||
name = TelegramUiHelper.getUserName(user)
|
||||
if (helper.isGroup(chat)) {
|
||||
photoPath = helper.getUserPhotoPath(user)
|
||||
groupPhotoPath = chat.photo?.small?.local?.path
|
||||
} else {
|
||||
photoPath = user.profilePhoto?.small?.local?.path
|
||||
}
|
||||
grayscalePhotoPath = helper.getUserGreyPhotoPath(user)
|
||||
placeholderId = R.drawable.img_user_picture
|
||||
userId = user.id
|
||||
privateChat = helper.isPrivateChat(chat) || helper.isSecretChat(chat)
|
||||
chatWithBot = helper.isBot(userId)
|
||||
lastUpdated = (gpx.modifiedTime / 1000).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
private fun gpxToUserGpxChatItem(
|
||||
helper: TelegramHelper,
|
||||
gpx: GPXUtilities.GPXFile
|
||||
): GpxChatItem? {
|
||||
val user = helper.getUser(gpx.userId) ?: return null
|
||||
return GpxChatItem().apply {
|
||||
gpxFile = gpx
|
||||
name = TelegramUiHelper.getUserName(user)
|
||||
photoPath = user.profilePhoto?.small?.local?.path
|
||||
grayscalePhotoPath = helper.getUserGreyPhotoPath(user)
|
||||
placeholderId = R.drawable.img_user_picture
|
||||
userId = user.id
|
||||
chatWithBot = helper.isBot(userId)
|
||||
lastUpdated = (gpx.modifiedTime / 1000).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ListItem {
|
||||
|
||||
var chatId: Long = 0
|
||||
|
@ -272,6 +320,24 @@ object TelegramUiHelper {
|
|||
override fun getVisibleName() = chatTitle
|
||||
}
|
||||
|
||||
class GpxChatItem : ListItem() {
|
||||
|
||||
var gpxFile: GPXUtilities.GPXFile? = null
|
||||
internal set
|
||||
var groupPhotoPath: String? = null
|
||||
internal set
|
||||
var privateChat: Boolean = false
|
||||
internal set
|
||||
var chatWithBot: Boolean = false
|
||||
internal set
|
||||
|
||||
override fun canBeOpenedOnMap() = latLon != null
|
||||
|
||||
override fun getMapPointId() = "${chatId}_$userId"
|
||||
|
||||
override fun getVisibleName() = chatTitle
|
||||
}
|
||||
|
||||
class LocationItem : ListItem() {
|
||||
|
||||
override fun canBeOpenedOnMap() = latLon != null
|
||||
|
|
|
@ -11,10 +11,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.*
|
||||
import net.osmand.Location
|
||||
import net.osmand.data.LatLon
|
||||
import net.osmand.telegram.R
|
||||
|
@ -22,6 +19,7 @@ import net.osmand.telegram.TelegramApplication
|
|||
import net.osmand.telegram.TelegramLocationProvider.TelegramCompassListener
|
||||
import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener
|
||||
import net.osmand.telegram.TelegramSettings
|
||||
import net.osmand.telegram.helpers.SavingTracksDbHelper
|
||||
import net.osmand.telegram.helpers.TelegramHelper.*
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper.ChatItem
|
||||
|
@ -33,6 +31,7 @@ import net.osmand.telegram.utils.OsmandFormatter
|
|||
import net.osmand.telegram.utils.UiUtils.UpdateLocationViewCache
|
||||
import net.osmand.util.MapUtils
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
import java.util.*
|
||||
|
||||
private const val CHAT_VIEW_TYPE = 0
|
||||
private const val LOCATION_ITEM_VIEW_TYPE = 1
|
||||
|
|
|
@ -27,6 +27,7 @@ import net.osmand.telegram.ui.MyLocationTabFragment.ActionButtonsListener
|
|||
import net.osmand.telegram.ui.views.LockableViewPager
|
||||
import net.osmand.telegram.utils.*
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
import java.io.File
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
const val OPEN_MY_LOCATION_TAB_KEY = "open_my_location_tab"
|
||||
|
@ -35,6 +36,7 @@ private const val PERMISSION_REQUEST_LOCATION = 1
|
|||
|
||||
private const val MY_LOCATION_TAB_POS = 0
|
||||
private const val LIVE_NOW_TAB_POS = 1
|
||||
private const val TIMELINE_TAB_POS = 2
|
||||
|
||||
class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListener, TelegramIncomingMessagesListener {
|
||||
|
||||
|
@ -54,6 +56,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
|
||||
private var myLocationTabFragment: MyLocationTabFragment? = null
|
||||
private var liveNowTabFragment: LiveNowTabFragment? = null
|
||||
private var timelineTabFragment: TimelineTabFragment? = null
|
||||
|
||||
private lateinit var buttonsBar: LinearLayout
|
||||
private lateinit var bottomNav: BottomNavigationView
|
||||
|
@ -72,7 +75,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
|
||||
val viewPager = findViewById<LockableViewPager>(R.id.view_pager).apply {
|
||||
swipeLocked = true
|
||||
offscreenPageLimit = 2
|
||||
offscreenPageLimit = 3
|
||||
adapter = ViewPagerAdapter(supportFragmentManager)
|
||||
}
|
||||
|
||||
|
@ -82,11 +85,13 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
when (it.itemId) {
|
||||
R.id.action_my_location -> pos = MY_LOCATION_TAB_POS
|
||||
R.id.action_live_now -> pos = LIVE_NOW_TAB_POS
|
||||
R.id.action_timeline -> pos = TIMELINE_TAB_POS
|
||||
}
|
||||
if (pos != -1 && pos != viewPager.currentItem) {
|
||||
when (pos) {
|
||||
MY_LOCATION_TAB_POS -> liveNowTabFragment?.tabClosed()
|
||||
LIVE_NOW_TAB_POS -> liveNowTabFragment?.tabOpened()
|
||||
TIMELINE_TAB_POS -> liveNowTabFragment?.tabClosed()
|
||||
}
|
||||
viewPager.currentItem = pos
|
||||
return@setOnNavigationItemSelectedListener true
|
||||
|
@ -139,10 +144,10 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
if (fragment is TelegramListener) {
|
||||
listeners.add(WeakReference(fragment))
|
||||
}
|
||||
if (fragment is MyLocationTabFragment) {
|
||||
myLocationTabFragment = fragment
|
||||
} else if (fragment is LiveNowTabFragment) {
|
||||
liveNowTabFragment = fragment
|
||||
when (fragment) {
|
||||
is MyLocationTabFragment -> myLocationTabFragment = fragment
|
||||
is LiveNowTabFragment -> liveNowTabFragment = fragment
|
||||
is TimelineTabFragment -> timelineTabFragment = fragment
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,6 +322,15 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
android.os.Process.killProcess(android.os.Process.myPid())
|
||||
}
|
||||
|
||||
fun shareGpx(path: String) {
|
||||
val fileUri = AndroidUtils.getUriForFile(app, File(path))
|
||||
val sendIntent = Intent(Intent.ACTION_SEND)
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
|
||||
sendIntent.type = "application/gpx+xml"
|
||||
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
startActivity(sendIntent)
|
||||
}
|
||||
|
||||
fun loginTelegram() {
|
||||
if (telegramHelper.getTelegramAuthorizationState() != TelegramAuthorizationState.CLOSED) {
|
||||
telegramHelper.logout()
|
||||
|
@ -463,7 +477,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
|
||||
class ViewPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
|
||||
|
||||
private val fragments = listOf<Fragment>(MyLocationTabFragment(), LiveNowTabFragment())
|
||||
private val fragments = listOf<Fragment>(MyLocationTabFragment(), LiveNowTabFragment(), TimelineTabFragment())
|
||||
|
||||
override fun getItem(position: Int) = fragments[position]
|
||||
|
||||
|
|
|
@ -146,8 +146,10 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
mainView.findViewById<TextView>(R.id.status_title).apply {
|
||||
val sharingStatus = getString(R.string.sharing_enabled)
|
||||
val spannable = SpannableString(sharingStatus)
|
||||
spannable.setSpan(ForegroundColorSpan(app.uiUtils.getActiveColor()),
|
||||
sharingStatus.indexOf(" "), sharingStatus.length, 0)
|
||||
spannable.setSpan(
|
||||
ForegroundColorSpan(app.uiUtils.getActiveColor()),
|
||||
sharingStatus.indexOf(" "), sharingStatus.length, 0
|
||||
)
|
||||
text = spannable
|
||||
}
|
||||
|
||||
|
@ -450,7 +452,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
textContainer.visibility = if (sharingMode) View.GONE else View.VISIBLE
|
||||
titleContainer.visibility = if (sharingMode) View.VISIBLE else View.GONE
|
||||
startSharingBtn.visibility = if (sharingMode) View.VISIBLE else View.GONE
|
||||
headerParams.scrollFlags = if (sharingMode) 0 else AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
|
||||
headerParams.scrollFlags =
|
||||
if (sharingMode) 0 else AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
|
||||
stopSharingSwitcher.isChecked = true
|
||||
appBarScrollRange = -1
|
||||
}
|
||||
|
@ -460,7 +463,12 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
settings.updateSharingStatusHistory()
|
||||
val sharingStatus = settings.sharingStatusChanges.last()
|
||||
sharingStatusTitle.text = sharingStatus.getTitle(app)
|
||||
sharingStatusIcon.setImageDrawable(app.uiUtils.getIcon(sharingStatus.statusType.iconId, sharingStatus.statusType.iconColorRes))
|
||||
sharingStatusIcon.setImageDrawable(
|
||||
app.uiUtils.getIcon(
|
||||
sharingStatus.statusType.iconId,
|
||||
sharingStatus.statusType.iconColorRes
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,7 +498,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
items.addAll(chats)
|
||||
if (!sharingMode) {
|
||||
for (user in contacts.values) {
|
||||
val containsInChats = chats.any { telegramHelper.getUserIdFromChatType(it.type) == user.id }
|
||||
val containsInChats =
|
||||
chats.any { telegramHelper.getUserIdFromChatType(it.type) == user.id }
|
||||
if ((!sharingMode && settings.isSharingLocationToUser(user.id)) || user.id == currentUser?.id || containsInChats) {
|
||||
continue
|
||||
}
|
||||
|
@ -521,7 +530,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
return list
|
||||
}
|
||||
|
||||
inner class MyLocationListAdapter : RecyclerView.Adapter<MyLocationListAdapter.BaseViewHolder>() {
|
||||
inner class MyLocationListAdapter :
|
||||
RecyclerView.Adapter<MyLocationListAdapter.BaseViewHolder>() {
|
||||
var items = mutableListOf<TdApi.Object>()
|
||||
set(value) {
|
||||
field = value
|
||||
|
@ -569,7 +579,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
}
|
||||
|
||||
val lastItem = position == itemCount - 1
|
||||
val placeholderId = if (isChat && telegramHelper.isGroup(item as TdApi.Chat)) R.drawable.img_group_picture else R.drawable.img_user_picture
|
||||
val placeholderId =
|
||||
if (isChat && telegramHelper.isGroup(item as TdApi.Chat)) R.drawable.img_group_picture else R.drawable.img_user_picture
|
||||
val live = (isChat && settings.isSharingLocationToChat(itemId))
|
||||
val shareInfo = if (isChat) settings.getChatsShareInfo()[itemId] else null
|
||||
|
||||
|
@ -588,7 +599,6 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
}
|
||||
|
||||
holder.title?.text = title
|
||||
|
||||
if (holder is ChatViewHolder) {
|
||||
holder.description?.visibility = View.GONE
|
||||
if (live) {
|
||||
|
@ -648,7 +658,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
|
||||
val duration = shareInfo?.userSetLivePeriod
|
||||
if (duration != null && duration > 0) {
|
||||
holder.descriptionDuration?.text = OsmandFormatter.getFormattedDuration(context!!, duration)
|
||||
holder.descriptionDuration?.text =
|
||||
OsmandFormatter.getFormattedDuration(context!!, duration)
|
||||
holder.description?.apply {
|
||||
visibility = View.VISIBLE
|
||||
text = "${getText(R.string.sharing_time)}:"
|
||||
|
@ -658,17 +669,29 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
val expiresIn = shareInfo?.getChatLiveMessageExpireTime() ?: 0
|
||||
|
||||
holder.textInArea?.apply {
|
||||
val time = shareInfo?.additionalActiveTime ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
|
||||
val time =
|
||||
shareInfo?.additionalActiveTime ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
|
||||
visibility = View.VISIBLE
|
||||
text = "+ ${OsmandFormatter.getFormattedDuration(context!!, time)}"
|
||||
setOnClickListener {
|
||||
val expireTime = shareInfo?.getChatLiveMessageExpireTime() ?: 0
|
||||
val newLivePeriod = expireTime + (shareInfo?.additionalActiveTime ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0])
|
||||
val nextAdditionalActiveTime = shareInfo?.getNextAdditionalActiveTime() ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[1]
|
||||
val newLivePeriod = expireTime + (shareInfo?.additionalActiveTime
|
||||
?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0])
|
||||
val nextAdditionalActiveTime = shareInfo?.getNextAdditionalActiveTime()
|
||||
?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[1]
|
||||
if (isChat) {
|
||||
settings.shareLocationToChat(itemId, true, newLivePeriod, nextAdditionalActiveTime)
|
||||
settings.shareLocationToChat(
|
||||
itemId,
|
||||
true,
|
||||
newLivePeriod,
|
||||
nextAdditionalActiveTime
|
||||
)
|
||||
} else {
|
||||
settings.shareLocationToUser(itemId.toInt(), newLivePeriod, nextAdditionalActiveTime)
|
||||
settings.shareLocationToUser(
|
||||
itemId.toInt(),
|
||||
newLivePeriod,
|
||||
nextAdditionalActiveTime
|
||||
)
|
||||
}
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
|
@ -686,13 +709,16 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
|
||||
holder.stopSharingSecondPart?.apply {
|
||||
visibility = getStopSharingVisibility(expiresIn)
|
||||
text = "(${getString(R.string.in_time,
|
||||
OsmandFormatter.getFormattedDuration(context!!, expiresIn, true))})"
|
||||
text = "(${getString(
|
||||
R.string.in_time,
|
||||
OsmandFormatter.getFormattedDuration(context!!, expiresIn, true)
|
||||
)})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStopSharingVisibility(expiresIn: Long) = if (expiresIn > 0) View.VISIBLE else View.INVISIBLE
|
||||
private fun getStopSharingVisibility(expiresIn: Long) =
|
||||
if (expiresIn > 0) View.VISIBLE else View.INVISIBLE
|
||||
|
||||
private fun removeItem(chat: TdApi.Object) {
|
||||
items.remove(chat)
|
||||
|
|
|
@ -0,0 +1,272 @@
|
|||
package net.osmand.telegram.ui
|
||||
|
||||
import android.app.DatePickerDialog
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.Switch
|
||||
import android.widget.TextView
|
||||
import net.osmand.PlatformUtil
|
||||
import net.osmand.telegram.R
|
||||
import net.osmand.telegram.TelegramApplication
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper.ListItem
|
||||
import net.osmand.telegram.ui.TimelineTabFragment.LiveNowListAdapter.BaseViewHolder
|
||||
import net.osmand.telegram.utils.AndroidUtils
|
||||
import net.osmand.telegram.utils.GPXUtilities
|
||||
import net.osmand.telegram.utils.OsmandFormatter
|
||||
import java.util.*
|
||||
|
||||
|
||||
class TimelineTabFragment : Fragment() {
|
||||
|
||||
private val log = PlatformUtil.getLog(TimelineTabFragment::class.java)
|
||||
|
||||
private val app: TelegramApplication
|
||||
get() = activity?.application as TelegramApplication
|
||||
|
||||
private val telegramHelper get() = app.telegramHelper
|
||||
private val settings get() = app.settings
|
||||
|
||||
private lateinit var adapter: LiveNowListAdapter
|
||||
|
||||
private lateinit var dateStartBtn: TextView
|
||||
private lateinit var dateEndBtn: TextView
|
||||
private lateinit var mainView: View
|
||||
|
||||
private var start = 0L
|
||||
private var end = 0L
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
mainView = inflater.inflate(R.layout.fragment_timeline_tab, container, false)
|
||||
val appBarLayout = mainView.findViewById<View>(R.id.app_bar_layout)
|
||||
|
||||
start = System.currentTimeMillis()
|
||||
end = System.currentTimeMillis()
|
||||
|
||||
AndroidUtils.addStatusBarPadding19v(context!!, appBarLayout)
|
||||
adapter = LiveNowListAdapter()
|
||||
mainView.findViewById<RecyclerView>(R.id.recycler_view).apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = this@TimelineTabFragment.adapter
|
||||
}
|
||||
|
||||
val switcher = mainView.findViewById<Switch>(R.id.monitoring_switcher)
|
||||
val monitoringTv = mainView.findViewById<TextView>(R.id.monitoring_title)
|
||||
monitoringTv.setText(if (settings.monitoringEnabled) R.string.monitoring_is_enabled else R.string.monitoring_is_disabled)
|
||||
|
||||
mainView.findViewById<View>(R.id.monitoring_container).setOnClickListener {
|
||||
val monitoringEnabled = !settings.monitoringEnabled
|
||||
settings.monitoringEnabled = monitoringEnabled
|
||||
switcher.isChecked = monitoringEnabled
|
||||
monitoringTv.setText(if (monitoringEnabled) R.string.monitoring_is_enabled else R.string.monitoring_is_disabled)
|
||||
}
|
||||
|
||||
dateStartBtn = mainView.findViewById<TextView>(R.id.date_start_btn).apply {
|
||||
setOnClickListener {
|
||||
selectStartDate()
|
||||
}
|
||||
setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_start), null, null, null)
|
||||
}
|
||||
dateEndBtn = mainView.findViewById<TextView>(R.id.date_end_btn).apply {
|
||||
setOnClickListener {
|
||||
selectEndDate()
|
||||
}
|
||||
setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_add), null, null, null)
|
||||
}
|
||||
|
||||
setupBtnTextColor(dateStartBtn)
|
||||
setupBtnTextColor(dateEndBtn)
|
||||
|
||||
return mainView
|
||||
}
|
||||
|
||||
private fun setupBtnTextColor(textView: TextView) {
|
||||
textView.setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light))
|
||||
}
|
||||
|
||||
private fun selectStartDate() {
|
||||
val dateFromDialog =
|
||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
val from = Calendar.getInstance()
|
||||
from.set(Calendar.YEAR, year)
|
||||
from.set(Calendar.MONTH, monthOfYear)
|
||||
from.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
from.set(Calendar.HOUR_OF_DAY, 0)
|
||||
from.clear(Calendar.MINUTE)
|
||||
from.clear(Calendar.SECOND)
|
||||
from.clear(Calendar.MILLISECOND)
|
||||
start = from.timeInMillis
|
||||
updateList()
|
||||
updateDateButtons()
|
||||
}
|
||||
val startCalendar = Calendar.getInstance()
|
||||
startCalendar.timeInMillis = start
|
||||
DatePickerDialog(context, dateFromDialog,
|
||||
startCalendar.get(Calendar.YEAR),
|
||||
startCalendar.get(Calendar.MONTH),
|
||||
startCalendar.get(Calendar.DAY_OF_MONTH)
|
||||
).show()
|
||||
}
|
||||
|
||||
private fun selectEndDate() {
|
||||
val dateFromDialog =
|
||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
val from = Calendar.getInstance()
|
||||
from.set(Calendar.YEAR, year)
|
||||
from.set(Calendar.MONTH, monthOfYear)
|
||||
from.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
from.set(Calendar.HOUR_OF_DAY, 23)
|
||||
from.set(Calendar.MINUTE, 59)
|
||||
from.set(Calendar.SECOND, 59)
|
||||
from.set(Calendar.MILLISECOND, 999)
|
||||
end = from.timeInMillis
|
||||
updateList()
|
||||
updateDateButtons()
|
||||
}
|
||||
val endCalendar = Calendar.getInstance()
|
||||
endCalendar.timeInMillis = end
|
||||
DatePickerDialog(context, dateFromDialog,
|
||||
endCalendar.get(Calendar.YEAR),
|
||||
endCalendar.get(Calendar.MONTH),
|
||||
endCalendar.get(Calendar.DAY_OF_MONTH)
|
||||
).show()
|
||||
}
|
||||
|
||||
private fun updateDateButtons() {
|
||||
dateStartBtn.text = OsmandFormatter.getFormattedDate(start / 1000)
|
||||
dateEndBtn.text = OsmandFormatter.getFormattedDate(end / 1000)
|
||||
dateEndBtn.setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_end), null, null, null)
|
||||
}
|
||||
|
||||
private fun getPressedStateIcon(@DrawableRes iconId: Int): Drawable? {
|
||||
val normal = app.uiUtils.getActiveIcon(iconId)
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
val active = app.uiUtils.getIcon(iconId, R.color.ctrl_light)
|
||||
if (normal != null && active != null) {
|
||||
return AndroidUtils.createPressedStateListDrawable(normal, active)
|
||||
}
|
||||
}
|
||||
return normal
|
||||
}
|
||||
|
||||
private fun updateList() {
|
||||
val res = mutableListOf<ListItem>()
|
||||
val s = System.currentTimeMillis()
|
||||
log.debug("updateList $s")
|
||||
val ignoredUsersIds = ArrayList<Int>()
|
||||
val currentUserId = telegramHelper.getCurrentUser()?.id
|
||||
if (currentUserId != null) {
|
||||
val currentUserGpx:GPXUtilities.GPXFile? = app.savingTracksDbHelper.collectRecordedDataForUser(currentUserId, 0, start, end)
|
||||
if (currentUserGpx != null) {
|
||||
TelegramUiHelper.gpxToChatItem(telegramHelper, currentUserGpx, true)?.also {
|
||||
res.add(it)
|
||||
}
|
||||
}
|
||||
ignoredUsersIds.add(currentUserId)
|
||||
}
|
||||
val gpxFiles = app.savingTracksDbHelper.collectRecordedDataForUsers(start, end, ignoredUsersIds)
|
||||
val e = System.currentTimeMillis()
|
||||
|
||||
gpxFiles.forEach {
|
||||
TelegramUiHelper.gpxToChatItem(telegramHelper, it,false)?.also { chatItem ->
|
||||
res.add(chatItem)
|
||||
}
|
||||
}
|
||||
|
||||
adapter.items = sortAdapterItems(res)
|
||||
log.debug("updateList $s dif: ${e - s}")
|
||||
}
|
||||
|
||||
private fun sortAdapterItems(list: MutableList<ListItem>): MutableList<ListItem> {
|
||||
val currentUserId = telegramHelper.getCurrentUser()?.id ?: 0
|
||||
list.sortWith(java.util.Comparator { lhs, rhs ->
|
||||
when (currentUserId) {
|
||||
lhs.userId -> return@Comparator 1
|
||||
rhs.userId -> return@Comparator 1
|
||||
else -> return@Comparator lhs.name.compareTo(rhs.name)
|
||||
}
|
||||
})
|
||||
return list
|
||||
}
|
||||
|
||||
inner class LiveNowListAdapter : RecyclerView.Adapter<BaseViewHolder>() {
|
||||
|
||||
var items: List<ListItem> = emptyList()
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return BaseViewHolder(inflater.inflate(R.layout.live_now_chat_card, parent, false))
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
||||
val lastItem = position == itemCount - 1
|
||||
val item = items[position]
|
||||
val currentUserId = telegramHelper.getCurrentUser()?.id ?: 0
|
||||
|
||||
TelegramUiHelper.setupPhoto(app, holder.icon, item.photoPath, R.drawable.img_user_picture_active, false)
|
||||
holder.title?.text = item.name
|
||||
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
|
||||
holder.lastTelegramUpdateTime?.visibility = View.GONE
|
||||
|
||||
if (item is TelegramUiHelper.GpxChatItem) {
|
||||
val gpx = item.gpxFile
|
||||
val groupDescrRowVisible = (!item.privateChat || item.chatWithBot) && item.userId != currentUserId
|
||||
if (groupDescrRowVisible) {
|
||||
holder.groupDescrContainer?.visibility = View.VISIBLE
|
||||
holder.groupTitle?.text = item.getVisibleName()
|
||||
TelegramUiHelper.setupPhoto(app, holder.groupImage, item.groupPhotoPath, item.placeholderId, false)
|
||||
} else {
|
||||
holder.groupDescrContainer?.visibility = View.GONE
|
||||
}
|
||||
holder.userRow?.setOnClickListener {
|
||||
if (gpx != null) {
|
||||
childFragmentManager.also {
|
||||
UserGpxInfoFragment.showInstance(it, gpx, start, end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
holder.imageButton?.visibility = View.GONE
|
||||
holder.showOnMapRow?.visibility = View.GONE
|
||||
holder.bottomDivider?.visibility = if (lastItem) View.GONE else View.VISIBLE
|
||||
holder.topDivider?.visibility = if (position != 0) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
inner class BaseViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val icon: ImageView? = view.findViewById(R.id.icon)
|
||||
val title: TextView? = view.findViewById(R.id.title)
|
||||
val description: TextView? = view.findViewById(R.id.description)
|
||||
val bottomShadow: View? = view.findViewById(R.id.bottom_shadow)
|
||||
val lastTelegramUpdateTime: TextView? = view.findViewById(R.id.last_telegram_update_time)
|
||||
|
||||
val userRow: View? = view.findViewById(R.id.user_row)
|
||||
val groupDescrContainer: View? = view.findViewById(R.id.group_container)
|
||||
val groupImage: ImageView? = view.findViewById(R.id.group_icon)
|
||||
val groupTitle: TextView? = view.findViewById(R.id.group_title)
|
||||
val imageButton: ImageView? = view.findViewById(R.id.image_button)
|
||||
val showOnMapRow: View? = view.findViewById(R.id.show_on_map_row)
|
||||
val topDivider: View? = view.findViewById(R.id.top_divider)
|
||||
val bottomDivider: View? = view.findViewById(R.id.bottom_divider)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,321 @@
|
|||
package net.osmand.telegram.ui
|
||||
|
||||
import android.app.DatePickerDialog
|
||||
import android.app.TimePickerDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import net.osmand.PlatformUtil
|
||||
import net.osmand.aidl.gpx.AGpxBitmap
|
||||
import net.osmand.telegram.R
|
||||
import net.osmand.telegram.helpers.OsmandAidlHelper
|
||||
import net.osmand.telegram.helpers.SavingTracksDbHelper
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.telegram.utils.AndroidUtils
|
||||
import net.osmand.telegram.utils.GPXUtilities
|
||||
import net.osmand.telegram.utils.OsmandFormatter
|
||||
import net.osmand.util.Algorithms
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class UserGpxInfoFragment : BaseDialogFragment() {
|
||||
|
||||
private val log = PlatformUtil.getLog(UserGpxInfoFragment::class.java)
|
||||
|
||||
private val uiUtils get() = app.uiUtils
|
||||
|
||||
private lateinit var gpxFile: GPXUtilities.GPXFile
|
||||
|
||||
private lateinit var dateStartBtn: TextView
|
||||
private lateinit var timeStartBtn: TextView
|
||||
private lateinit var dateEndBtn: TextView
|
||||
private lateinit var timeEndBtn: TextView
|
||||
|
||||
private lateinit var avgElevationTv: TextView
|
||||
private lateinit var avgSpeedTv: TextView
|
||||
private lateinit var totalDistanceTv: TextView
|
||||
private lateinit var timeSpanTv: TextView
|
||||
|
||||
private var startCalendar = Calendar.getInstance()
|
||||
private var endCalendar = Calendar.getInstance()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
parent: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val mainView = inflater.inflate(R.layout.fragment_user_gpx_info, parent)
|
||||
AndroidUtils.addStatusBarPadding19v(context!!, mainView)
|
||||
|
||||
readFromBundle(savedInstanceState ?: arguments)
|
||||
|
||||
val userId = gpxFile.userId
|
||||
val chatId = gpxFile.chatId
|
||||
|
||||
val user = app.telegramHelper.getUser(userId)
|
||||
if (user != null) {
|
||||
mainView.findViewById<TextView>(R.id.title).text = TelegramUiHelper.getUserName(user)
|
||||
TelegramUiHelper.setupPhoto(app, mainView.findViewById<ImageView>(R.id.user_icon),
|
||||
telegramHelper.getUserPhotoPath(user), R.drawable.img_user_placeholder, false)
|
||||
}
|
||||
app.osmandAidlHelper.setGpxBitmapCreatedListener(
|
||||
object : OsmandAidlHelper.GpxBitmapCreatedListener {
|
||||
override fun onGpxBitmapCreated(bitmap: AGpxBitmap) {
|
||||
activity?.runOnUiThread {
|
||||
mainView.findViewById<ImageView>(R.id.gpx_map).setImageDrawable(BitmapDrawable(app.resources, bitmap.bitmap))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
updateGPXMap()
|
||||
|
||||
val backBtn = mainView.findViewById<ImageView>(R.id.back_button)
|
||||
backBtn.setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_arrow_back))
|
||||
backBtn.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
dateStartBtn = mainView.findViewById<TextView>(R.id.date_start_btn)
|
||||
timeStartBtn = mainView.findViewById<TextView>(R.id.time_start_btn)
|
||||
dateEndBtn = mainView.findViewById<TextView>(R.id.date_end_btn)
|
||||
timeEndBtn = mainView.findViewById<TextView>(R.id.time_end_btn)
|
||||
|
||||
dateStartBtn.setOnClickListener { selectStartDate() }
|
||||
timeStartBtn.setOnClickListener { selectStartTime() }
|
||||
dateEndBtn.setOnClickListener { selectEndDate() }
|
||||
timeEndBtn.setOnClickListener { selectEndTime() }
|
||||
|
||||
setupBtnTextColor(dateStartBtn)
|
||||
setupBtnTextColor(timeStartBtn)
|
||||
setupBtnTextColor(dateEndBtn)
|
||||
setupBtnTextColor(timeEndBtn)
|
||||
|
||||
updateDateAndTimeButtons()
|
||||
|
||||
avgElevationTv = mainView.findViewById<TextView>(R.id.average_altitude_text)
|
||||
avgSpeedTv = mainView.findViewById<TextView>(R.id.average_speed_text)
|
||||
totalDistanceTv = mainView.findViewById<TextView>(R.id.distance_text)
|
||||
timeSpanTv = mainView.findViewById<TextView>(R.id.duration_text)
|
||||
|
||||
mainView.findViewById<ImageView>(R.id.average_altitude_icon).apply {
|
||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range))
|
||||
}
|
||||
mainView.findViewById<ImageView>(R.id.average_speed_icon).apply {
|
||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_speed_average))
|
||||
}
|
||||
mainView.findViewById<ImageView>(R.id.distance_icon).apply {
|
||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range))
|
||||
}
|
||||
mainView.findViewById<ImageView>(R.id.duration_icon).apply {
|
||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range))
|
||||
}
|
||||
|
||||
updateGPXStatisticRow()
|
||||
|
||||
mainView.findViewById<ImageView>(R.id.open_in_osmand_icon).setImageResource(R.drawable.ic_logo_osmand_free)
|
||||
|
||||
mainView.findViewById<LinearLayout>(R.id.open_in_osmand_btn).apply {
|
||||
setOnClickListener {
|
||||
val gpx = gpxFile
|
||||
if (gpx.path.isNotEmpty()) {
|
||||
openGpx(gpx.path)
|
||||
} else {
|
||||
saveCurrentGpxToFile(object :
|
||||
SavingTracksDbHelper.SaveGpxListener {
|
||||
override fun onSavingGpxFinish(path: String) {
|
||||
openGpx(path)
|
||||
}
|
||||
|
||||
override fun onSavingGpxError(warnings: MutableList<String>?) {
|
||||
Toast.makeText(app, warnings?.firstOrNull(), Toast.LENGTH_LONG).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mainView.findViewById<ImageView>(R.id.share_gpx_icon).setImageDrawable(uiUtils.getActiveIcon(R.drawable.ic_action_share))
|
||||
|
||||
mainView.findViewById<LinearLayout>(R.id.share_gpx_btn).apply {
|
||||
setOnClickListener {
|
||||
val gpx = gpxFile
|
||||
if (gpx.path.isNotEmpty()) {
|
||||
(activity as MainActivity).shareGpx(gpx.path)
|
||||
} else {
|
||||
saveCurrentGpxToFile(object :
|
||||
SavingTracksDbHelper.SaveGpxListener {
|
||||
override fun onSavingGpxFinish(path: String) {
|
||||
(activity as MainActivity).shareGpx(path)
|
||||
}
|
||||
|
||||
override fun onSavingGpxError(warnings: MutableList<String>?) {
|
||||
Toast.makeText(app, warnings?.firstOrNull(), Toast.LENGTH_LONG).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mainView
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putLong(START_KEY, startCalendar.timeInMillis)
|
||||
outState.putLong(END_KEY, endCalendar.timeInMillis)
|
||||
}
|
||||
|
||||
private fun openGpx(path: String) {
|
||||
val fileUri = AndroidUtils.getUriForFile(app, File(path))
|
||||
val openGpxIntent = Intent(Intent.ACTION_VIEW)
|
||||
openGpxIntent.setDataAndType(fileUri, "application/gpx+xml")
|
||||
openGpxIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
val resolved = activity?.packageManager?.resolveActivity(openGpxIntent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||
if (resolved != null) {
|
||||
startActivity(openGpxIntent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveCurrentGpxToFile(listener: SavingTracksDbHelper.SaveGpxListener) {
|
||||
app.savingTracksDbHelper.saveGpx(listener, app.getExternalFilesDir(null), gpxFile)
|
||||
}
|
||||
|
||||
private fun readFromBundle(bundle: Bundle?) {
|
||||
bundle?.also {
|
||||
startCalendar.timeInMillis = it.getLong(START_KEY)
|
||||
endCalendar.timeInMillis = it.getLong(END_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupBtnTextColor(textView: TextView) {
|
||||
textView.setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light))
|
||||
}
|
||||
|
||||
private fun updateGpxInfo() {
|
||||
gpxFile = app.savingTracksDbHelper.collectRecordedDataForUser(gpxFile.userId, gpxFile.chatId, startCalendar.timeInMillis, endCalendar.timeInMillis)
|
||||
updateGPXStatisticRow()
|
||||
updateDateAndTimeButtons()
|
||||
updateGPXMap()
|
||||
}
|
||||
|
||||
private fun updateDateAndTimeButtons() {
|
||||
dateStartBtn.text = SimpleDateFormat("dd MMM", Locale.getDefault()).format(startCalendar.timeInMillis)
|
||||
dateEndBtn.text = SimpleDateFormat("dd MMM", Locale.getDefault()).format(endCalendar.timeInMillis)
|
||||
|
||||
timeStartBtn.text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(startCalendar.timeInMillis)
|
||||
timeEndBtn.text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(endCalendar.timeInMillis)
|
||||
}
|
||||
|
||||
private fun updateGPXStatisticRow() {
|
||||
val analysis: GPXUtilities.GPXTrackAnalysis = gpxFile.getAnalysis(0)
|
||||
avgElevationTv.text = OsmandFormatter.getFormattedAlt(analysis.avgElevation, app)
|
||||
avgSpeedTv.text = if (analysis.isSpeedSpecified) OsmandFormatter.getFormattedSpeed(analysis.avgSpeed, app) else ""
|
||||
totalDistanceTv.text = OsmandFormatter.getFormattedDistance(analysis.totalDistance, app)
|
||||
timeSpanTv.text = Algorithms.formatDuration((analysis.timeSpan / 1000).toInt(), true)
|
||||
}
|
||||
|
||||
private fun updateGPXMap() {
|
||||
saveCurrentGpxToFile(object :
|
||||
SavingTracksDbHelper.SaveGpxListener {
|
||||
override fun onSavingGpxFinish(path: String) {
|
||||
val mgr = activity?.getSystemService(Context.WINDOW_SERVICE)
|
||||
if (mgr != null) {
|
||||
val dm = DisplayMetrics()
|
||||
(mgr as WindowManager).defaultDisplay.getMetrics(dm)
|
||||
val widthPixels = dm.widthPixels - (2 * app.resources.getDimensionPixelSize(R.dimen.content_padding_standard))
|
||||
val heightPixels = AndroidUtils.dpToPx(app, 152f)
|
||||
val gpxUri = AndroidUtils.getUriForFile(app, File(path))
|
||||
app.osmandAidlHelper.getBitmapForGpx(gpxUri, dm.density , widthPixels, heightPixels, GPX_TRACK_COLOR)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSavingGpxError(warnings: MutableList<String>?) {
|
||||
log.debug("onSavingGpxError ${warnings?.firstOrNull()}")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun selectStartDate() {
|
||||
val dateFromDialog =
|
||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
startCalendar.set(Calendar.YEAR, year)
|
||||
startCalendar.set(Calendar.MONTH, monthOfYear)
|
||||
startCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
updateGpxInfo()
|
||||
}
|
||||
DatePickerDialog(context, dateFromDialog,
|
||||
startCalendar.get(Calendar.YEAR),
|
||||
startCalendar.get(Calendar.MONTH),
|
||||
startCalendar.get(Calendar.DAY_OF_MONTH)).show()
|
||||
}
|
||||
|
||||
private fun selectStartTime() {
|
||||
TimePickerDialog(context,
|
||||
TimePickerDialog.OnTimeSetListener { _, hours, minutes ->
|
||||
startCalendar.set(Calendar.HOUR_OF_DAY, hours)
|
||||
startCalendar.set(Calendar.MINUTE, minutes)
|
||||
updateGpxInfo()
|
||||
}, 0, 0, true).show()
|
||||
}
|
||||
|
||||
private fun selectEndDate() {
|
||||
val dateFromDialog =
|
||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
endCalendar.set(Calendar.YEAR, year)
|
||||
endCalendar.set(Calendar.MONTH, monthOfYear)
|
||||
endCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
updateGpxInfo()
|
||||
}
|
||||
DatePickerDialog(context, dateFromDialog,
|
||||
endCalendar.get(Calendar.YEAR),
|
||||
endCalendar.get(Calendar.MONTH),
|
||||
endCalendar.get(Calendar.DAY_OF_MONTH)).show()
|
||||
}
|
||||
|
||||
private fun selectEndTime() {
|
||||
TimePickerDialog(context,
|
||||
TimePickerDialog.OnTimeSetListener { _, hours, minutes ->
|
||||
endCalendar.set(Calendar.HOUR_OF_DAY, hours)
|
||||
endCalendar.set(Calendar.MINUTE, minutes)
|
||||
updateGpxInfo()
|
||||
}, 0, 0, true).show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val TAG = "UserGpxInfoFragment"
|
||||
private const val START_KEY = "start_key"
|
||||
private const val END_KEY = "end_key"
|
||||
|
||||
private const val GPX_TRACK_COLOR = -65536
|
||||
|
||||
fun showInstance(fm: FragmentManager, gpxFile: GPXUtilities.GPXFile, start: Long, end: Long): Boolean {
|
||||
return try {
|
||||
val fragment = UserGpxInfoFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putLong(START_KEY, start)
|
||||
putLong(END_KEY, end)
|
||||
}
|
||||
}
|
||||
fragment.gpxFile = gpxFile
|
||||
fragment.show(fm, TAG)
|
||||
true
|
||||
} catch (e: RuntimeException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1808
OsmAnd-telegram/src/net/osmand/telegram/utils/GPXUtilities.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
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);
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ object OsmandFormatter {
|
|||
private const val SHORT_TIME_FORMAT = "%02d:%02d"
|
||||
private const val SIMPLE_TIME_OF_DAY_FORMAT = "HH:mm"
|
||||
private const val SIMPLE_DATE_FORMAT = "dd MMM HH:mm:ss"
|
||||
private const val SHORT_DATE_FORMAT = "dd MMM yyyy"
|
||||
|
||||
private const val MIN_DURATION_FOR_DATE_FORMAT = 48 * 60 * 60
|
||||
|
||||
|
@ -77,8 +78,13 @@ object OsmandFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
fun getFormattedDate(seconds: Long): String =
|
||||
fun getFormattedDate(seconds: Long, shortFormat: Boolean = false): String {
|
||||
return if (shortFormat) {
|
||||
SimpleDateFormat(SIMPLE_DATE_FORMAT, Locale.getDefault()).format(seconds * 1000L)
|
||||
} else {
|
||||
SimpleDateFormat(SHORT_DATE_FORMAT, Locale.getDefault()).format(seconds * 1000L)
|
||||
}
|
||||
}
|
||||
|
||||
fun getListItemLiveTimeDescr(ctx: TelegramApplication, lastUpdated: Int, prefix: String = ""): String {
|
||||
return if (lastUpdated > 0) {
|
||||
|
|
|
@ -163,24 +163,12 @@
|
|||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="file"/>
|
||||
<data android:host="*"/>
|
||||
<data android:pathPattern=".*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kml" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter
|
||||
android:label="@string/app_name"
|
||||
android:priority="50">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
<data android:pathPattern="*.kml"/>
|
||||
<data android:pathPattern=".*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kml" />
|
||||
|
@ -194,8 +182,11 @@
|
|||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
<data android:pathPattern=".*\\.kmz" />
|
||||
<data android:pathPattern=".*\\..*\\.kmz" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kmz" />
|
||||
|
@ -271,9 +262,12 @@
|
|||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
<data android:pathPattern="*.sqlitedb" />
|
||||
<data android:pathPattern=".*\\.sqlitedb" />
|
||||
<data android:pathPattern=".*\\..*\\.sqlitedb" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.sqlitedb" />
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<asset source="voice/fa/fa_tts.js" destination="voice/fa-tts/fa_tts.js" mode="overwriteOnlyIfExists" />
|
||||
<asset source="voice/fi/fi_tts.js" destination="voice/fi-tts/fi_tts.js" mode="overwriteOnlyIfExists" />
|
||||
<asset source="voice/fr/fr_tts.js" destination="voice/fr-tts/fr_tts.js" mode="alwaysOverwriteOrCopy" />
|
||||
<asset source="voice/gn-py/gn-py_tts.js" destination="voice/gn-py-tts/gn-py_tts.js" mode="overwriteOnlyIfExists" />
|
||||
<!--<asset source="voice/he/he_tts.js" destination="voice/he-tts/he_tts.js" mode="overwriteOnlyIfExists" />-->
|
||||
<asset source="voice/nb/nb_tts.js" destination="voice/nb-tts/nb_tts.js" mode="overwriteOnlyIfExists" />
|
||||
<asset source="voice/hi/hi_tts.js" destination="voice/hi-tts/hi_tts.js" mode="overwriteOnlyIfExists" />
|
||||
|
|
BIN
OsmAnd/res/drawable-large-hdpi/map_nautical_bearing.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
OsmAnd/res/drawable-large-hdpi/map_nautical_bearing_night.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
OsmAnd/res/drawable-large-hdpi/map_nautical_location.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
OsmAnd/res/drawable-large-hdpi/map_nautical_location_night.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.2 KiB |
BIN
OsmAnd/res/drawable-large-xhdpi/map_nautical_bearing.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
OsmAnd/res/drawable-large-xhdpi/map_nautical_bearing_night.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
OsmAnd/res/drawable-large-xhdpi/map_nautical_location.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
OsmAnd/res/drawable-large-xhdpi/map_nautical_location_night.png
Normal file
After Width: | Height: | Size: 4 KiB |
After Width: | Height: | Size: 7 KiB |