kopia lustrzana https://github.com/sh123/codec2_talkie
Show station track together with info window
rodzic
4dcd4c5c4c
commit
7968612cf2
|
@ -39,6 +39,7 @@ dependencies {
|
|||
implementation 'com.github.mik3y:usb-serial-for-android:3.4.3'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata:2.5.1'
|
||||
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
|
|
|
@ -44,11 +44,13 @@ import org.osmdroid.views.overlay.Polygon;
|
|||
import org.osmdroid.views.overlay.Polyline;
|
||||
import org.osmdroid.views.overlay.compass.CompassOverlay;
|
||||
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider;
|
||||
import org.osmdroid.views.overlay.infowindow.MarkerInfoWindow;
|
||||
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
|
||||
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -57,22 +59,24 @@ public class MapActivity extends AppCompatActivity {
|
|||
|
||||
private MapView _map;
|
||||
private IMapController _mapController;
|
||||
private CompassOverlay _compassOverlay;
|
||||
private MyLocationNewOverlay _myLocationNewOverlay;
|
||||
private final HashMap<String, Marker> _objectOverlayItems = new HashMap<>();
|
||||
private final HashMap<String, Polygon> _objectOverlayRangeCircles = new HashMap<>();
|
||||
|
||||
private StationItemViewModel _stationItemViewModel;
|
||||
private PositionItemViewModel _positionItemViewModel;
|
||||
private AprsSymbolTable _aprsSymbolTable;
|
||||
private MarkerInfoWindow _infoWindow;
|
||||
|
||||
private String _mySymbolCode;
|
||||
// live settings
|
||||
private boolean _rotateMap = false;
|
||||
private boolean _showCircles = false;
|
||||
|
||||
private LiveData<List<PositionItem>> _stationTrack;
|
||||
List<GeoPoint> _stationTrackPoints = new ArrayList<>();
|
||||
Polyline _stationTrackLine = new Polyline(); //see note below!
|
||||
// stations and circles
|
||||
private final HashMap<String, Marker> _objectOverlayItems = new HashMap<>();
|
||||
private final HashMap<String, Polygon> _objectOverlayRangeCircles = new HashMap<>();
|
||||
|
||||
// track
|
||||
private LiveData<List<PositionItem>> _activeTrackLiveData;
|
||||
private final HashSet<Long> _activeTrackTimestamps = new HashSet<>();
|
||||
private final List<GeoPoint> _activeTrackPoints = new ArrayList<>();
|
||||
private final Polyline _activeTrackLine = new Polyline();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -88,12 +92,13 @@ public class MapActivity extends AppCompatActivity {
|
|||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
_aprsSymbolTable = AprsSymbolTable.getInstance(context);
|
||||
_mySymbolCode = sharedPreferences.getString(PreferenceKeys.APRS_SYMBOL, "/[");
|
||||
String mySymbolCode = sharedPreferences.getString(PreferenceKeys.APRS_SYMBOL, "/[");
|
||||
|
||||
// map
|
||||
_map = findViewById(R.id.map);
|
||||
_map.setTileSource(TileSourceFactory.MAPNIK);
|
||||
_map.setMultiTouchControls(true);
|
||||
_infoWindow = new MarkerInfoWindow(R.layout.bonuspack_bubble, _map);
|
||||
|
||||
// controller
|
||||
_mapController = _map.getController();
|
||||
|
@ -109,13 +114,13 @@ public class MapActivity extends AppCompatActivity {
|
|||
super.onSensorChanged(sensorEvent);
|
||||
}
|
||||
};
|
||||
_compassOverlay = new CompassOverlay(context, compassOrientationProvider, _map);
|
||||
_compassOverlay.enableCompass();
|
||||
_map.getOverlays().add(_compassOverlay);
|
||||
CompassOverlay compassOverlay = new CompassOverlay(context, compassOrientationProvider, _map);
|
||||
compassOverlay.enableCompass();
|
||||
_map.getOverlays().add(compassOverlay);
|
||||
|
||||
// my location
|
||||
_myLocationNewOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(context), _map);
|
||||
Bitmap myBitmapIcon = _aprsSymbolTable.bitmapFromSymbol(_mySymbolCode, true);
|
||||
Bitmap myBitmapIcon = _aprsSymbolTable.bitmapFromSymbol(mySymbolCode, true);
|
||||
_myLocationNewOverlay.setDirectionIcon(myBitmapIcon);
|
||||
_myLocationNewOverlay.setPersonIcon(myBitmapIcon);
|
||||
|
||||
|
@ -131,27 +136,27 @@ public class MapActivity extends AppCompatActivity {
|
|||
_positionItemViewModel = new ViewModelProvider(this).get(PositionItemViewModel.class);
|
||||
|
||||
// station items, add data listener
|
||||
_stationItemViewModel = new ViewModelProvider(this).get(StationItemViewModel.class);
|
||||
StationItemViewModel _stationItemViewModel = new ViewModelProvider(this).get(StationItemViewModel.class);
|
||||
// FIXME, room livedata sends all list if one item changed event with distinctUntilChanged
|
||||
_stationItemViewModel.getAllStationItems().observe(this, allStations -> {
|
||||
Log.i(TAG, "add stations " + allStations.size());
|
||||
for (StationItem station : allStations) {
|
||||
//Log.i(TAG, "new position " + station.getLatitude() + " " + station.getLongitude());
|
||||
// do not add items without coordinate
|
||||
if (station.getMaidenHead() == null) continue;
|
||||
if (addStationPositionIcon(station)) {
|
||||
addRangeCircle(station);
|
||||
} else {
|
||||
Log.e(TAG, "Failed to add APRS icon for " + station.getSrcCallsign() + ", " + station.getSymbolCode());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// add track
|
||||
Paint p = _stationTrackLine.getOutlinePaint();
|
||||
Paint p = _activeTrackLine.getOutlinePaint();
|
||||
p.setStrokeWidth(8);
|
||||
p.setColor(Color.RED);
|
||||
p.setStyle(Paint.Style.STROKE);
|
||||
p.setPathEffect(new DashPathEffect(new float[] {10f, 10f}, 0f));
|
||||
_map.getOverlayManager().add(_stationTrackLine);
|
||||
_map.getOverlayManager().add(_activeTrackLine);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -194,21 +199,41 @@ public class MapActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
private void addTrack(List<PositionItem> positions) {
|
||||
boolean shouldSet = false;
|
||||
for (PositionItem trackPoint : positions) {
|
||||
//Log.i(TAG, "addPoint " + trackPoint.getLatitude() + " " + trackPoint.getLongitude());
|
||||
_stationTrackPoints.add(new GeoPoint(trackPoint.getLatitude(), trackPoint.getLongitude()));
|
||||
if (!_activeTrackTimestamps.contains(trackPoint.getTimestampEpoch())) {
|
||||
Log.i(TAG, "addPoint " + trackPoint.getTimestampEpoch() + " " + trackPoint.getLatitude() + " " + trackPoint.getLongitude());
|
||||
GeoPoint point = new GeoPoint(trackPoint.getLatitude(), trackPoint.getLongitude());
|
||||
_activeTrackPoints.add(point);
|
||||
_activeTrackTimestamps.add(trackPoint.getTimestampEpoch());
|
||||
shouldSet = true;
|
||||
}
|
||||
}
|
||||
_stationTrackLine.setPoints(_stationTrackPoints);
|
||||
if (shouldSet)
|
||||
_activeTrackLine.setPoints(_activeTrackPoints);
|
||||
}
|
||||
|
||||
private boolean addStationPositionIcon(StationItem group) {
|
||||
String callsign = group.getSrcCallsign();
|
||||
Marker marker = null;
|
||||
|
||||
String newTitle = DateTools.epochToIso8601(group.getTimestampEpoch()) + " " + callsign;
|
||||
String newSnippet = getStatus(group);
|
||||
|
||||
// find old marker
|
||||
if (_objectOverlayItems.containsKey(callsign)) {
|
||||
marker = _objectOverlayItems.get(callsign);
|
||||
assert marker != null;
|
||||
|
||||
// skip if unchanged
|
||||
GeoPoint oldPosition = marker.getPosition();
|
||||
if (oldPosition.getLatitude() == group.getLatitude() &&
|
||||
oldPosition.getLongitude() == group.getLongitude() &&
|
||||
marker.getTitle().equals(newTitle) &&
|
||||
marker.getSnippet().equals(newSnippet)) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// create new marker
|
||||
|
@ -274,25 +299,28 @@ public class MapActivity extends AppCompatActivity {
|
|||
marker.setId(callsign);
|
||||
marker.setIcon(drawableText);
|
||||
marker.setImage(drawableInfoIcon);
|
||||
/*
|
||||
marker.setOnMarkerClickListener((monitoredMarker, mapView) -> {
|
||||
if (_stationTrack != null)
|
||||
_stationTrack.removeObservers(this);
|
||||
_map.getOverlays().remove(_stationTrackLine);
|
||||
_stationTrackPoints.clear();
|
||||
_stationTrackLine.setPoints(_stationTrackPoints);
|
||||
_map.getOverlays().add(_stationTrackLine);
|
||||
_stationTrack = _positionItemViewModel.getPositionItems(monitoredMarker.getId());
|
||||
_stationTrack.observe(this, this::addTrack);
|
||||
GeoPoint markerPoint = monitoredMarker.getPosition();
|
||||
_infoWindow.open(monitoredMarker, new GeoPoint(markerPoint.getLatitude(), markerPoint.getLongitude()), 0, -2*height);
|
||||
if (_activeTrackLiveData != null)
|
||||
_activeTrackLiveData.removeObservers(this);
|
||||
_map.getOverlays().remove(_activeTrackLine);
|
||||
_activeTrackPoints.clear();
|
||||
_activeTrackTimestamps.clear();
|
||||
_activeTrackLine.setPoints(_activeTrackPoints);
|
||||
_map.getOverlays().add(_activeTrackLine);
|
||||
// FIXME, room livedata sends all list if one item changed event with distinctUntilChanged
|
||||
_activeTrackLiveData = _positionItemViewModel.getPositionItems(monitoredMarker.getId());
|
||||
_activeTrackLiveData.observe(this, this::addTrack);
|
||||
return false;
|
||||
});
|
||||
*/
|
||||
_map.getOverlays().add(marker);
|
||||
_objectOverlayItems.put(callsign, marker);
|
||||
}
|
||||
|
||||
marker.setPosition(new GeoPoint(group.getLatitude(), group.getLongitude()));
|
||||
marker.setTitle(DateTools.epochToIso8601(group.getTimestampEpoch()) + " " + callsign);
|
||||
marker.setSnippet(getStatus(group));
|
||||
marker.setTitle(newTitle);
|
||||
marker.setSnippet(newSnippet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -108,10 +108,12 @@ public class PositionItem {
|
|||
|
||||
public void setRangeMiles(double rangeMiles) { this.rangeMiles = rangeMiles; }
|
||||
|
||||
public static boolean equalTo(PositionItem positionItem1, PositionItem positionItem2) {
|
||||
return positionItem1.getSrcCallsign().equals(positionItem2.getSrcCallsign()) &
|
||||
positionItem1.getIsTransmit() == positionItem2.getIsTransmit() &&
|
||||
Math.abs(positionItem1.getLongitude() - positionItem2.getLongitude()) <= MIN_COORDINATE_CHANGE_DELTA &
|
||||
Math.abs(positionItem1.getLatitude() - positionItem2.getLatitude()) <= MIN_COORDINATE_CHANGE_DELTA;
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
PositionItem positionItem = (PositionItem) o;
|
||||
return getSrcCallsign().equals(positionItem.getSrcCallsign()) &
|
||||
getIsTransmit() == positionItem.getIsTransmit() &&
|
||||
Math.abs(getLongitude() - positionItem.getLongitude()) <= MIN_COORDINATE_CHANGE_DELTA &
|
||||
Math.abs(getLatitude() - positionItem.getLatitude()) <= MIN_COORDINATE_CHANGE_DELTA;
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ public abstract class PositionItemDao {
|
|||
@Transaction
|
||||
public void upsertPositionItem(PositionItem positionItem) {
|
||||
PositionItem oldPosition = getLastPositionItem(positionItem.getSrcCallsign());
|
||||
if (oldPosition != null && PositionItem.equalTo(positionItem, oldPosition)) {
|
||||
if (oldPosition != null && oldPosition.equals(positionItem)) {
|
||||
// update id and coordinates from existing position
|
||||
positionItem.setId(oldPosition.getId());
|
||||
positionItem.setLatitude(oldPosition.getLatitude());
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.radio.codec2talkie.storage.position;
|
|||
import android.app.Application;
|
||||
import android.util.Log;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.Transformations;
|
||||
|
||||
import com.radio.codec2talkie.storage.AppDatabase;
|
||||
|
||||
|
||||
|
@ -23,7 +25,7 @@ public class PositionItemRepository {
|
|||
}
|
||||
|
||||
public LiveData<List<PositionItem>> getPositionItems(String srcCallsign) {
|
||||
return _positionItemDao.getPositionItems(srcCallsign);
|
||||
return Transformations.distinctUntilChanged(_positionItemDao.getPositionItems(srcCallsign));
|
||||
}
|
||||
|
||||
public void deleteAllPositionItems() {
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package com.radio.codec2talkie.storage.station;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity(indices = {@Index(value = {"srcCallsign"}, unique = true)})
|
||||
public class StationItem {
|
||||
@NonNull
|
||||
|
@ -118,4 +122,15 @@ public class StationItem {
|
|||
if (stationItem.getLogLine() != null)
|
||||
setLogLine(stationItem.getLogLine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
StationItem stationItem = (StationItem)o;
|
||||
return srcCallsign.equals(stationItem.getSrcCallsign()) &&
|
||||
timestampEpoch == stationItem.getTimestampEpoch() &&
|
||||
Objects.equals(comment, stationItem.getComment()) &&
|
||||
Objects.equals(dstCallsign, stationItem.getDstCallsign()) &&
|
||||
latitude == stationItem.getLatitude() &&
|
||||
longitude == stationItem.getLongitude();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.database.sqlite.SQLiteConstraintException;
|
|||
import android.util.Log;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.Transformations;
|
||||
|
||||
import com.radio.codec2talkie.storage.AppDatabase;
|
||||
|
||||
|
@ -19,7 +20,7 @@ public class StationItemRepository {
|
|||
public StationItemRepository(Application application) {
|
||||
AppDatabase appDatabase = AppDatabase.getDatabase(application);
|
||||
_stationItemDao = appDatabase.stationitemDao();
|
||||
_stationItems = _stationItemDao.getAllStationItems();
|
||||
_stationItems = Transformations.distinctUntilChanged(_stationItemDao.getAllStationItems());
|
||||
}
|
||||
|
||||
public LiveData<List<StationItem>> getAllStationItems() { return _stationItems; }
|
||||
|
|
Ładowanie…
Reference in New Issue