Merge pull request #10382 from osmandapp/obf_bookmarks

Obf bookmarks
This commit is contained in:
alex-osm 2020-12-18 14:30:17 +03:00 committed by GitHub
commit 3a5ff92470
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 265 additions and 73 deletions

View file

@ -1538,9 +1538,20 @@ public class BinaryMapIndexReader {
return request;
}
public static SearchRequest<RouteDataObject> buildSearchRouteRequest(int sleft, int sright, int stop, int sbottom,
ResultMatcher<RouteDataObject> matcher){
public static SearchRequest<Amenity> buildSearchPoiRequest(LatLon latLon, int radius, int zoom,
SearchPoiTypeFilter poiTypeFilter,
ResultMatcher<Amenity> matcher) {
SearchRequest<Amenity> request = new SearchRequest<>();
request.setBBoxRadius(latLon.getLatitude(), latLon.getLongitude(), radius);
request.zoom = zoom;
request.poiTypeFilter = poiTypeFilter;
request.resultMatcher = matcher;
return request;
}
public static SearchRequest<RouteDataObject> buildSearchRouteRequest(int sleft, int sright, int stop, int sbottom,
ResultMatcher<RouteDataObject> matcher) {
SearchRequest<RouteDataObject> request = new SearchRequest<RouteDataObject>();
request.left = sleft;
request.right = sright;

View file

@ -461,7 +461,6 @@ public class AppInitializer implements IProgress {
// TODOTRAVEL_OBF_HELPER check ResourceManager and use TravelObfHelper
app.travelHelper = !TravelDbHelper.checkIfDbFileExists(app) ? new TravelObfHelper(app) : new TravelDbHelper(app);
app.travelHelper.initializeDataOnAppStartup();
app.travelHelper = startupInit(app.travelHelper, TravelHelper.class);
app.lockHelper = startupInit(new LockHelper(app), LockHelper.class);
@ -661,7 +660,7 @@ public class AppInitializer implements IProgress {
initPoiTypes();
notifyEvent(InitEvents.POI_TYPES_INITIALIZED);
app.resourceManager.reloadIndexesOnStart(this, warnings);
app.travelHelper.initializeDataOnAppStartup();
// native depends on renderers
initNativeCore();
notifyEvent(InitEvents.NATIVE_INITIALIZED);

View file

@ -801,7 +801,7 @@ public class ResourceManager {
return warnings;
}
private List<BinaryMapIndexReader> getTravelRepositories() {
public List<BinaryMapIndexReader> getTravelRepositories() {
List<String> fileNames = new ArrayList<>(travelRepositories.keySet());
Collections.sort(fileNames, Algorithms.getStringVersionComparator());
List<BinaryMapIndexReader> res = new ArrayList<>();
@ -814,7 +814,7 @@ public class ResourceManager {
return res;
}
private List<BinaryMapIndexReader> getTravelRepositories(double topLat, double leftLon, double bottomLat, double rightLon) {
public List<BinaryMapIndexReader> getTravelRepositories(double topLat, double leftLon, double bottomLat, double rightLon) {
List<String> fileNames = new ArrayList<>(travelRepositories.keySet());
Collections.sort(fileNames, Algorithms.getStringVersionComparator());
int leftX31 = MapUtils.get31TileNumberX(leftLon);

View file

@ -3,11 +3,8 @@ package net.osmand.plus.wikivoyage.data;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.OsmandApplication;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -30,13 +27,14 @@ public interface TravelHelper {
Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(
final TravelArticle article);
@Nullable
TravelArticle getArticleById(String routeId, String lang);
TravelArticle getArticleByTitle(String title, String lang);
String getArticleId(String title, String lang);
ArrayList<String> getArticleLangs(String articleId);
ArrayList<String> getArticleLangs(String routeId);
String getGPXName(TravelArticle article);

View file

@ -118,6 +118,7 @@ public class TravelLocalDataHelper {
saved.content = WikiArticleHelper.getPartialContent(article.getContent());
saved.lat = article.lat;
saved.lon = article.lon;
saved.routeId = article.routeId;
savedArticles.add(saved);
dbHelper.addSavedArticle(saved);
notifySavedUpdated();
@ -168,7 +169,7 @@ public class TravelLocalDataHelper {
private static class WikivoyageLocalDataDbHelper {
private static final int DB_VERSION = 4;
private static final int DB_VERSION = 5;
private static final String DB_NAME = "wikivoyage_local_data";
private static final String HISTORY_TABLE_NAME = "wikivoyage_search_history";
@ -202,6 +203,7 @@ public class TravelLocalDataHelper {
private static final String BOOKMARKS_COL_TRAVEL_BOOK = "travel_book";
private static final String BOOKMARKS_COL_LAT = "lat";
private static final String BOOKMARKS_COL_LON = "lon";
private static final String BOOKMARKS_COL_ROUTE_ID = "route_id";
private static final String BOOKMARKS_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS " +
BOOKMARKS_TABLE_NAME + " (" +
@ -212,7 +214,8 @@ public class TravelLocalDataHelper {
BOOKMARKS_COL_PARTIAL_CONTENT + " TEXT, " +
BOOKMARKS_COL_TRAVEL_BOOK + " TEXT, " +
BOOKMARKS_COL_LAT + " double, " +
BOOKMARKS_COL_LON + " double);";
BOOKMARKS_COL_LON + " double, " +
BOOKMARKS_COL_ROUTE_ID + " TEXT" + ");";
private static final String BOOKMARKS_TABLE_SELECT = "SELECT " +
BOOKMARKS_COL_ARTICLE_TITLE + ", " +
@ -221,7 +224,8 @@ public class TravelLocalDataHelper {
BOOKMARKS_COL_IMAGE_TITLE + ", " +
BOOKMARKS_COL_PARTIAL_CONTENT + ", " +
BOOKMARKS_COL_LAT + ", " +
BOOKMARKS_COL_LON +
BOOKMARKS_COL_LON + ", " +
BOOKMARKS_COL_ROUTE_ID +
" FROM " + BOOKMARKS_TABLE_NAME;
private final OsmandApplication context;
@ -271,6 +275,9 @@ public class TravelLocalDataHelper {
conn.execSQL("ALTER TABLE " + BOOKMARKS_TABLE_NAME + " ADD " + BOOKMARKS_COL_LAT + " double");
conn.execSQL("ALTER TABLE " + BOOKMARKS_TABLE_NAME + " ADD " + BOOKMARKS_COL_LON + " double");
}
if (oldVersion < 5) {
conn.execSQL("ALTER TABLE " + BOOKMARKS_TABLE_NAME + " ADD " + BOOKMARKS_COL_ROUTE_ID + " TEXT");
}
}
@NonNull
@ -420,11 +427,12 @@ public class TravelLocalDataHelper {
BOOKMARKS_COL_PARTIAL_CONTENT + ", " +
BOOKMARKS_COL_TRAVEL_BOOK + ", " +
BOOKMARKS_COL_LAT + ", " +
BOOKMARKS_COL_LON +
") VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
BOOKMARKS_COL_LON + ", " +
BOOKMARKS_COL_ROUTE_ID +
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
conn.execSQL(query, new Object[]{article.title, article.lang,
article.aggregatedPartOf, article.imageTitle, article.content,
travelBook, article.lat, article.lon});
travelBook, article.lat, article.lon, article.routeId});
} finally {
conn.close();
}
@ -475,6 +483,7 @@ public class TravelLocalDataHelper {
res.content = cursor.getString(cursor.getColumnIndex(BOOKMARKS_COL_PARTIAL_CONTENT));
res.lat = cursor.getDouble(cursor.getColumnIndex(BOOKMARKS_COL_LAT));
res.lon = cursor.getDouble(cursor.getColumnIndex(BOOKMARKS_COL_LON));
res.routeId = cursor.getString(cursor.getColumnIndex(BOOKMARKS_COL_ROUTE_ID));
return res;
}

View file

@ -1,20 +1,21 @@
package net.osmand.plus.wikivoyage.data;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.Collator;
import net.osmand.CollatorStringMatcher;
import net.osmand.GPXUtilities;
import net.osmand.IndexConstants;
import net.osmand.OsmAndCollator;
import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.Amenity;
import net.osmand.data.MapObject;
import net.osmand.data.LatLon;
import net.osmand.osm.PoiCategory;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.api.SQLiteAPI;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
@ -22,54 +23,138 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static net.osmand.CollatorStringMatcher.StringMatcherMode.*;
public class TravelObfHelper implements TravelHelper {
private static final Log LOG = PlatformUtil.getLog(TravelObfHelper.class);
public static final String ROUTE_ARTICLE = "route_article";
public static final int SEARCH_RADIUS = 100000;
private final OsmandApplication app;
private final OsmandApplication application;
private List<TravelArticle> popularArticles = new ArrayList<>();
private final Map<String, TravelArticle> cachedArticles;
private final TravelLocalDataHelper localDataHelper;
private TravelLocalDataHelper localDataHelper;
private List<TravelArticle> popularArticles = new ArrayList<TravelArticle>();
public TravelObfHelper(OsmandApplication application) {
this.application = application;
localDataHelper = new TravelLocalDataHelper(application);
public TravelObfHelper(OsmandApplication app) {
this.app = app;
localDataHelper = new TravelLocalDataHelper(app);
cachedArticles = new HashMap<>();
}
@Override
public TravelLocalDataHelper getBookmarksHelper() {
return localDataHelper;
}
@Override
public void initializeDataOnAppStartup() {
}
@Override
public boolean isAnyTravelBookPresent() {
return checkIfObfFileExists(application);
}
public void initializeDataToDisplay() {
localDataHelper.refreshCachedData();
loadPopularArticles();
}
@NonNull
public List<TravelArticle> loadPopularArticles() {
String language = app.getLanguage();
popularArticles.clear();
List<Amenity> amenities;
for (BinaryMapIndexReader travelBookReader : getTravelBookReaders()) {
try {
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
BinaryMapIndexReader.SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
location, SEARCH_RADIUS, -1, getSearchRouteArticleFilter(), null);
amenities = travelBookReader.searchPoi(req);
if (amenities.size() > 0) {
for (Amenity a : amenities) {
if (!Algorithms.isEmpty(a.getName(language))) {
TravelArticle article = readArticle(a, language);
popularArticles.add(article);
cachedArticles.put(article.routeId, article);
if (popularArticles.size() >= 100) {
break;
}
}
}
Collections.sort(popularArticles, new Comparator<TravelArticle>() {
@Override
public int compare(TravelArticle article1, TravelArticle article2) {
int d1 = (int) (MapUtils.getDistance(article1.getLat(), article1.getLon(),
location.getLatitude(), location.getLongitude()));
int d2 = (int) (MapUtils.getDistance(article2.getLat(), article2.getLon(),
location.getLatitude(), location.getLongitude()));
return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1);
}
});
}
} catch (Exception e) {
LOG.error(e.getMessage());
}
}
return popularArticles;
}
BinaryMapIndexReader.SearchPoiTypeFilter getSearchRouteArticleFilter() {
return new BinaryMapIndexReader.SearchPoiTypeFilter() {
@Override
public boolean accept(PoiCategory type, String subcategory) {
return subcategory.equals(ROUTE_ARTICLE);
}
@Override
public boolean isEmpty() {
return false;
}
};
}
private TravelArticle readArticle(Amenity amenity, String lang) {
TravelArticle res = new TravelArticle();
res.title = Algorithms.isEmpty(amenity.getName(lang)) ? amenity.getName() : amenity.getName(lang);
res.content = amenity.getDescription(lang);
res.isPartOf = emptyIfNull(amenity.getTagContent(Amenity.IS_PART, lang));
res.lat = amenity.getLocation().getLatitude();
res.lon = amenity.getLocation().getLongitude();
res.imageTitle = emptyIfNull(amenity.getTagContent(Amenity.IMAGE_TITLE, lang));
res.routeId = getRouteId(amenity);
res.originalId = 0; //?
res.lang = lang;
res.contentsJson = emptyIfNull(amenity.getTagContent(Amenity.CONTENT_JSON, lang));
res.aggregatedPartOf = emptyIfNull(amenity.getTagContent(Amenity.IS_AGGR_PART, lang));
return res;
}
private String emptyIfNull(String text) {
return text == null ? "" : text;
}
private String getRouteId(Amenity amenity) {
return amenity.getTagContent(Amenity.ROUTE_ID, null);
}
@Override
public boolean isAnyTravelBookPresent() {
return !Algorithms.isEmpty(getTravelBookReaders());
}
@NonNull
public List<WikivoyageSearchResult> search(final String searchQuery) {
@Override
public List<WikivoyageSearchResult> search(String searchQuery) {
List<WikivoyageSearchResult> res = new ArrayList<>();
return res;
}
@NonNull
@Override
public List<TravelArticle> getPopularArticles() {
return popularArticles;
}
@ -81,38 +166,137 @@ public class TravelObfHelper implements TravelHelper {
@Override
public TravelArticle getArticleById(String routeId, String lang) {
return null;
TravelArticle article = cachedArticles.get(routeId);
if (article != null) {
return article;
} else {
return getArticleByIdFromTravelBooks(routeId, lang);
}
}
public TravelArticle getArticleByIdFromTravelBooks(final String routeId, final String lang) {
TravelArticle article = null;
final List<Amenity> amenities = new ArrayList<>();
for (BinaryMapIndexReader travelBookReader : getTravelBookReaders()) {
try {
int left = 0;
int right = Integer.MAX_VALUE;
int top = 0;
int bottom = Integer.MAX_VALUE;
BinaryMapIndexReader.SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
left, right, top, bottom, -1, getSearchRouteArticleFilter(),
new ResultMatcher<Amenity>() {
@Override
public boolean publish(Amenity amenity) {
if (getRouteId(amenity).equals(routeId)) {
amenities.add(amenity);
}
return false;
}
@Override
public boolean isCancelled() {
return false;
}
});
travelBookReader.searchPoi(req);
} catch (IOException e) {
LOG.error(e.getMessage());
}
if (!amenities.isEmpty()) {
article = readArticle(amenities.get(0), lang);
cachedArticles.put(article.routeId, article);
}
}
return article;
}
@Override
public TravelArticle getArticleByTitle(String title, String lang) {
return null;
public TravelArticle getArticleByTitle(final String title, final String lang) {
TravelArticle article = null;
final List<Amenity> amenities = new ArrayList<>();
for (BinaryMapIndexReader travelBookReader : getTravelBookReaders()) {
try {
int left = 0;
int right = Integer.MAX_VALUE;
int top = 0;
int bottom = Integer.MAX_VALUE;
BinaryMapIndexReader.SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
0, 0, title, left, right, top, bottom,
new ResultMatcher<Amenity>() {
@Override
public boolean publish(Amenity amenity) {
Collator collator = OsmAndCollator.primaryCollator();
if (CollatorStringMatcher.cmatches(collator, title, amenity.getName(lang),
CHECK_EQUALS_FROM_SPACE) && amenity.getSubType().equals(ROUTE_ARTICLE)) {
amenities.add(amenity);
}
return false;
}
@Override
public boolean isCancelled() {
return false;
}
});
travelBookReader.searchPoiByName(req);
} catch (IOException e) {
LOG.error(e.getMessage());
}
if (!amenities.isEmpty()) {
article = readArticle(amenities.get(0), lang);
cachedArticles.put(article.routeId, article);
}
}
return article;
}
private List<BinaryMapIndexReader> getTravelBookReaders() {
if (!app.isApplicationInitializing()) {
return app.getResourceManager().getTravelRepositories();
} else {
return new ArrayList<>();
}
}
@Override
public String getArticleId(String title, String lang) {
for (TravelArticle article : cachedArticles.values()) {
if (article.getTitle().equals(title)) {
return article.getRouteId();
}
}
TravelArticle article = getArticleByTitle(title, lang);
if (article != null) {
return article.getRouteId();
}
return null;
}
@Override
public ArrayList<String> getArticleLangs(String articleId) {
return null;
}
@NonNull
public List<TravelArticle> loadPopularArticles() {
popularArticles = new ArrayList<>();
return popularArticles;
public ArrayList<String> getArticleLangs(String routeId) {
ArrayList<String> res = new ArrayList<>();
res.add("en");
for (TravelArticle article : popularArticles) {
if (article.getRouteId().equals(routeId)) {
res.add(article.getLang());
}
}
return res;
}
@Override
public String getGPXName(TravelArticle article) {
return article.getTitle().replace('/', '_').replace('\'', '_')
.replace('\"', '_') + IndexConstants.GPX_FILE_EXT;
}
@Override
public File createGpxFile(TravelArticle article) {
final GPXUtilities.GPXFile gpx = article.getGpxFile();
File file = application.getAppPath(IndexConstants.GPX_TRAVEL_DIR + getGPXName(article));
File file = app.getAppPath(IndexConstants.GPX_TRAVEL_DIR + getGPXName(article));
if (!file.exists()) {
GPXUtilities.writeGpxFile(file, gpx);
}
@ -121,18 +305,6 @@ public class TravelObfHelper implements TravelHelper {
@Override
public String getSelectedTravelBookName() {
return null;
return "";
}
public static boolean checkIfObfFileExists(OsmandApplication app) {
File[] files = app.getAppPath(IndexConstants.WIKIVOYAGE_INDEX_DIR).listFiles();
if (files != null) {
for (File f : files) {
if (f.getName().contains(IndexConstants.BINARY_TRAVEL_GUIDE_MAP_INDEX_EXT)) {
return true;
}
}
}
return false;
}
}
}

View file

@ -38,6 +38,7 @@ import net.osmand.plus.wikipedia.WikiArticleHelper;
import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
import net.osmand.plus.wikivoyage.data.TravelArticle;
import net.osmand.plus.wikivoyage.data.TravelHelper;
import net.osmand.plus.wikivoyage.data.TravelLocalDataHelper;
import net.osmand.plus.wikivoyage.search.WikivoyageSearchDialogFragment;
import net.osmand.util.Algorithms;
@ -45,7 +46,8 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class WikivoyageExploreActivity extends TabActivity implements DownloadEvents, OnDialogFragmentResultListener {
public class WikivoyageExploreActivity extends TabActivity implements DownloadEvents, OnDialogFragmentResultListener,
TravelLocalDataHelper.Listener {
private static final String TAB_SELECTED = "tab_selected";
private static final String ROUTE_ID_KEY = "route_id_key";
@ -59,7 +61,6 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
protected List<WeakReference<Fragment>> fragments = new ArrayList<>();
private LockableViewPager viewPager;
private boolean updateNeeded;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -190,6 +191,7 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
setIntent(null);
}
getMyApplication().getDownloadThread().setUiActivity(this);
app.getTravelHelper().getBookmarksHelper().addListener(this);
}
protected void parseLaunchIntentLink(Uri data) {
@ -211,6 +213,7 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
protected void onPause() {
super.onPause();
getMyApplication().getDownloadThread().resetUiActivity(this);
app.getTravelHelper().getBookmarksHelper().removeListener(this);
}
@Nullable
@ -225,7 +228,7 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
}
@Nullable
private SavedArticlesTabFragment getSavedArticlesTabFragment() {
public SavedArticlesTabFragment getSavedArticlesTabFragment() {
for (WeakReference<Fragment> ref : fragments) {
Fragment f = ref.get();
if (f instanceof SavedArticlesTabFragment) {
@ -319,16 +322,13 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
updateFragments();
}
private void updateFragments() {
public void updateFragments() {
ExploreTabFragment exploreTabFragment = getExploreTabFragment();
SavedArticlesTabFragment savedArticlesTabFragment = getSavedArticlesTabFragment();
if (exploreTabFragment != null && savedArticlesTabFragment != null
&& exploreTabFragment.isAdded() && savedArticlesTabFragment.isAdded()) {
exploreTabFragment.populateData();
savedArticlesTabFragment.savedArticlesUpdated();
updateNeeded = false;
} else {
updateNeeded = true;
}
}
@ -353,9 +353,12 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
}
public void onTabFragmentResume(Fragment fragment) {
if (updateNeeded) {
updateFragments();
}
updateFragments();
}
@Override
public void savedArticlesUpdated() {
updateFragments();
}
private static class LoadWikivoyageData extends AsyncTask<Void, Void, Void> {