Merge remote-tracking branch 'origin/master'

This commit is contained in:
Weblate 2017-05-02 11:09:49 +02:00
commit 28a0169859
29 changed files with 659 additions and 4 deletions

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:drawable="@drawable/mapillary_button_idle"/>
</ripple>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="-10dp"
android:left="-10dp"
android:right="-10dp"
android:top="-10dp">
<shape android:shape="rectangle">
<stroke
android:width="12dp"
android:color="@color/ctx_menu_info_view_bg_dark" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<nine-patch android:src="@drawable/bg_card_shadow" />
</item>
</layer-list>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="-10dp"
android:left="-10dp"
android:right="-10dp"
android:top="-10dp">
<shape android:shape="rectangle">
<stroke
android:width="12dp"
android:color="@color/ctx_menu_info_view_bg_light" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<nine-patch android:src="@drawable/bg_card_shadow" />
</item>
</layer-list>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/mapillary_button_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/mapillary_button_idle"/>
</selector>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/mapillary_color"/>
</shape>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/mapillary_color_pressed"/>
</shape>

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/mapillary_card_width"
android:layout_height="@dimen/mapillary_card_height"
android:background="?attr/bg_card"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="100dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:maxLines="4"
android:gravity="center"
android:ellipsize="end"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:text="@string/mapillary_action_descr"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@drawable/mapillary_button"
android:layout_gravity="bottom|center_horizontal"
android:drawableLeft="@drawable/ic_action_mapillary"
android:drawableStart="@drawable/ic_action_mapillary"
android:drawablePadding="8dp"
android:paddingLeft="10dp"
android:paddingRight="14dp"
android:textColor="@color/color_white"
android:text="@string/shared_string_add_photos"/>
</LinearLayout>

View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/mapillary_card_width"
android:layout_height="@dimen/mapillary_card_height"
android:orientation="vertical">
<FrameLayout
android:id="@+id/image_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:src="@drawable/ic_logo_mapillary"/>
<TextView
android:id="@+id/watermark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:paddingLeft="4dp"
android:paddingTop="4dp"
android:paddingRight="8dp"
android:paddingBottom="8dp"
android:background="@color/popup_bg_color"
android:textColor="@color/color_white"
android:textSize="@dimen/default_sub_text_size"
tools:text="\@user123 | mapillary.com"/>
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/context_menu_card"/>
</FrameLayout>
</LinearLayout>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/mapillary_card_width"
android:layout_height="@dimen/mapillary_card_height"
android:background="?attr/bg_card"
android:gravity="center"
android:orientation="vertical">
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

View file

@ -16,6 +16,7 @@
<attr name="expandable_list_background" format="color"/>
<attr name="bg_color" format="reference" />
<attr name="bg_card" format="reference" />
<attr name="context_menu_card" format="reference" />
<attr name="bg_map_context_menu" format="reference" />
<attr name="bg_point_editor_view" format="reference" />
<attr name="ctx_menu_info_view_bg" format="reference" />

View file

@ -2,6 +2,7 @@
<resources>
<color name="mapillary_color">#3db878</color>
<color name="mapillary_color_pressed">#3a9f73</color>
<color name="buy_button_color">#50ae55</color>
<color name="buy_button_pressed_color">#b5e5b9</color>

View file

@ -10,4 +10,8 @@
<dimen name="quick_action_widget_height_big">200dp</dimen>
<dimen name="quick_action_widget_height_small">100dp</dimen>
<dimen name="mapillary_card_width">280dp</dimen>
<dimen name="mapillary_card_height">160dp</dimen>
</resources>

View file

@ -9,6 +9,8 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
-->
<string name="shared_string_add_photos">Add photos</string>
<string name="mapillary_action_descr">Contribute with your own street-level views of this location with Mapillary.</string>
<string name="mapillary_widget">Mapillary widget</string>
<string name="mapillary_widget_descr">Allow you to quick contribute to Mapillary</string>
<string name="mapillary_descr">Online Street-Photos for everyone. Discover places, collaborate, capture the world.</string>

View file

@ -96,6 +96,7 @@
<item name="actionBarStyle">@style/Widget.Styled.ActionBarLight</item>
<item name="bg_color">@color/bg_color_light</item>
<item name="bg_card">@drawable/bg_card_light</item>
<item name="context_menu_card">@drawable/context_menu_card_light</item>
<item name="bg_map_context_menu">@drawable/bg_map_context_menu_light</item>
<item name="bottom_menu_view_bg">@drawable/bg_bottom_menu_light</item>
<item name="left_menu_view_bg">@drawable/bg_left_menu_light</item>
@ -266,6 +267,7 @@
<item name="actionBarStyle">@style/Widget.Styled.ActionBarDark</item>
<item name="bg_color">@color/bg_color_dark</item>
<item name="bg_card">@drawable/bg_card_dark</item>
<item name="context_menu_card">@drawable/context_menu_card_dark</item>
<item name="bg_map_context_menu">@drawable/bg_map_context_menu_dark</item>
<item name="bottom_menu_view_bg">@drawable/bg_bottom_menu_dark</item>
<item name="left_menu_view_bg">@drawable/bg_left_menu_dark</item>

View file

@ -1,26 +1,41 @@
package net.osmand;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.Version;
import net.osmand.plus.resources.ResourceManager;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.Map;
public class AndroidNetworkUtils {
private static final int CONNECTION_TIMEOUT = 15000;
private static final Log LOG = PlatformUtil.getLog(AndroidNetworkUtils.class);
public interface OnRequestResultListener {
void onResult(String result);
}
@ -153,6 +168,27 @@ public class AndroidNetworkUtils {
return null;
}
public static Bitmap downloadImage(OsmandApplication ctx, String url) {
Bitmap res = null;
try {
URLConnection connection = NetworkUtils.getHttpURLConnection(url);
connection.setRequestProperty("User-Agent", Version.getFullVersion(ctx));
connection.setConnectTimeout(CONNECTION_TIMEOUT);
connection.setReadTimeout(CONNECTION_TIMEOUT);
BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream(), 8 * 1024);
try {
res = BitmapFactory.decodeStream(inputStream);
} finally {
Algorithms.closeStream(inputStream);
}
} catch (UnknownHostException e) {
LOG.error("UnknownHostException, cannot download image " + url + " " + e.getMessage());
} catch (Exception e) {
LOG.error("Cannot download image : " + url, e);
}
return res;
}
private static void showToast(OsmandApplication ctx, String message) {
ctx.showToastMessage(message);
}

View file

@ -7,8 +7,17 @@ import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.IProgress;
import net.osmand.Location;
import net.osmand.PlatformUtil;
@ -19,6 +28,7 @@ import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.dashboard.tools.DashFragmentData;
import net.osmand.plus.development.OsmandDevelopmentPlugin;
import net.osmand.plus.distancecalculator.DistanceCalculatorPlugin;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
import net.osmand.plus.myplaces.FavoritesActivity;
@ -100,6 +110,9 @@ public abstract class OsmandPlugin {
return null;
}
public void buildContextMenuRows(@NonNull MenuBuilder menuBuilder, @NonNull View view) {
}
public static void initPlugins(OsmandApplication app) {
OsmandSettings settings = app.getSettings();
Set<String> enabledPlugins = settings.getEnabledPlugins();

View file

@ -31,6 +31,7 @@ import net.osmand.data.QuadRect;
import net.osmand.osm.PoiCategory;
import net.osmand.plus.IconsCache;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.render.RenderingIcons;
@ -57,6 +58,7 @@ public class MenuBuilder {
private LatLon latLon;
private boolean showNearestWiki = false;
protected List<Amenity> nearestWiki = new ArrayList<>();
private List<Class<? extends OsmandPlugin>> pluginMenuBuilders = new ArrayList<>();
public class PlainMenuItem {
private int iconId;
@ -100,6 +102,10 @@ public class MenuBuilder {
plainMenuItems = new LinkedList<>();
}
public OsmandApplication getApp() {
return app;
}
public LatLon getLatLon() {
return latLon;
}
@ -121,12 +127,17 @@ public class MenuBuilder {
this.showNearestWiki = showNearestWiki;
}
public void addPluginMenuBuilder(Class<? extends OsmandPlugin> pluginClass) {
pluginMenuBuilders.add(pluginClass);
}
public void setLight(boolean light) {
this.light = light;
}
public void build(View view) {
firstRow = true;
buildPluginRows(view);
buildNearestWikiRow(view);
if (needBuildPlainMenuItems()) {
buildPlainMenuItems(view);
@ -146,6 +157,15 @@ public class MenuBuilder {
return true;
}
protected void buildPluginRows(View view) {
for (Class<? extends OsmandPlugin> pluginClass : pluginMenuBuilders) {
OsmandPlugin plugin = OsmandPlugin.getEnabledPlugin(pluginClass);
if (plugin != null) {
plugin.buildContextMenuRows(this, view);
}
}
}
protected void buildNearestWikiRow(View view) {
if (processNearstWiki() && nearestWiki.size() > 0) {
buildRow(view, R.drawable.ic_action_wikipedia, app.getString(R.string.wiki_around) + " (" + nearestWiki.size()+")", 0,
@ -161,7 +181,7 @@ public class MenuBuilder {
buildRowDivider(view, false);
}
protected boolean isFirstRow() {
public boolean isFirstRow() {
return firstRow;
}
@ -354,7 +374,7 @@ public class MenuBuilder {
rowBuilt();
}
protected void buildRowDivider(View view, boolean matchWidth) {
public void buildRowDivider(View view, boolean matchWidth) {
View horizontalLine = new View(view.getContext());
LinearLayout.LayoutParams llHorLineParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPx(1f));
llHorLineParams.gravity = Gravity.BOTTOM;

View file

@ -30,6 +30,7 @@ import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.views.POIMapLayer;
import net.osmand.util.Algorithms;
@ -49,6 +50,7 @@ public class AmenityMenuBuilder extends MenuBuilder {
public AmenityMenuBuilder(MapActivity mapActivity, final Amenity amenity) {
super(mapActivity);
this.amenity = amenity;
addPluginMenuBuilder(MapillaryPlugin.class);
setShowNearestWiki(true, amenity.getId());
}

View file

@ -11,6 +11,7 @@ import net.osmand.data.TransportStop;
import net.osmand.osm.PoiCategory;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.util.MapUtils;
import java.util.List;
@ -23,6 +24,7 @@ public class FavouritePointMenuBuilder extends MenuBuilder {
public FavouritePointMenuBuilder(MapActivity mapActivity, final FavouritePoint fav) {
super(mapActivity);
this.fav = fav;
addPluginMenuBuilder(MapillaryPlugin.class);
setShowNearestWiki(true);
acquireOriginObject();
}

View file

@ -7,6 +7,7 @@ import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.plus.views.POIMapLayer;
import net.osmand.util.Algorithms;
@ -20,6 +21,7 @@ public class WptPtMenuBuilder extends MenuBuilder {
public WptPtMenuBuilder(MapActivity mapActivity, final WptPt wpt) {
super(mapActivity);
this.wpt = wpt;
addPluginMenuBuilder(MapillaryPlugin.class);
setShowNearestWiki(true);
}

View file

@ -2,7 +2,6 @@ package net.osmand.plus.mapcontextmenu.controllers;
import android.graphics.drawable.Drawable;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
@ -10,6 +9,7 @@ import net.osmand.plus.activities.search.SearchHistoryFragment;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.util.Algorithms;
public class HistoryMenuController extends MenuController {
@ -20,6 +20,7 @@ public class HistoryMenuController extends MenuController {
public HistoryMenuController(MapActivity mapActivity, PointDescription pointDescription, final HistoryEntry entry) {
super(new MenuBuilder(mapActivity), pointDescription, mapActivity);
this.entry = entry;
builder.addPluginMenuBuilder(MapillaryPlugin.class);
builder.setShowNearestWiki(true);
initData();
}

View file

@ -2,7 +2,6 @@ package net.osmand.plus.mapcontextmenu.controllers;
import android.graphics.drawable.Drawable;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.MapMarkersHelper;
import net.osmand.plus.MapMarkersHelper.MapMarker;
@ -11,6 +10,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.MapMarkerDialogHelper;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.util.Algorithms;
public class MapMarkerMenuController extends MenuController {
@ -20,6 +20,7 @@ public class MapMarkerMenuController extends MenuController {
public MapMarkerMenuController(MapActivity mapActivity, PointDescription pointDescription, MapMarker mapMarker) {
super(new MenuBuilder(mapActivity), pointDescription, mapActivity);
this.mapMarker = mapMarker;
builder.addPluginMenuBuilder(MapillaryPlugin.class);
builder.setShowNearestWiki(true);
final MapMarkersHelper markersHelper = mapActivity.getMyApplication().getMapMarkersHelper();
leftTitleButtonController = new TitleButtonController() {

View file

@ -8,11 +8,13 @@ import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapillary.MapillaryPlugin;
public class MyLocationMenuController extends MenuController {
public MyLocationMenuController(MapActivity mapActivity, PointDescription pointDescription) {
super(new MenuBuilder(mapActivity), pointDescription, mapActivity);
builder.addPluginMenuBuilder(MapillaryPlugin.class);
builder.setShowNearestWiki(true);
}

View file

@ -8,6 +8,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.search.SearchHistoryFragment;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.util.Algorithms;
public class PointDescriptionMenuController extends MenuController {
@ -16,6 +17,7 @@ public class PointDescriptionMenuController extends MenuController {
public PointDescriptionMenuController(MapActivity mapActivity, final PointDescription pointDescription) {
super(new MenuBuilder(mapActivity), pointDescription, mapActivity);
builder.addPluginMenuBuilder(MapillaryPlugin.class);
builder.setShowNearestWiki(true);
initData();
}

View file

@ -8,6 +8,7 @@ import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.render.RenderingIcons;
import net.osmand.util.Algorithms;
@ -18,6 +19,7 @@ public class RenderedObjectMenuController extends MenuController {
public RenderedObjectMenuController(MapActivity mapActivity, PointDescription pointDescription, final RenderedObject renderedObject) {
super(new MenuBuilder(mapActivity), pointDescription, mapActivity);
builder.addPluginMenuBuilder(MapillaryPlugin.class);
builder.setShowNearestWiki(true);
this.renderedObject = renderedObject;
}

View file

@ -9,6 +9,7 @@ import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.util.Algorithms;
@ -19,6 +20,7 @@ public class TargetPointMenuController extends MenuController {
public TargetPointMenuController(MapActivity mapActivity, PointDescription pointDescription, TargetPoint targetPoint) {
super(new MenuBuilder(mapActivity), pointDescription, mapActivity);
this.targetPoint = targetPoint;
builder.addPluginMenuBuilder(MapillaryPlugin.class);
builder.setShowNearestWiki(true);
final TargetPointsHelper targetPointsHelper = getMapActivity().getMyApplication().getTargetPointsHelper();
final int intermediatePointsCount = targetPointsHelper.getIntermediatePoints().size();

View file

@ -0,0 +1,124 @@
package net.osmand.plus.mapillary;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import static java.text.DateFormat.FULL;
public class MapillaryImageInfo {
// (optional) Image's camera angle in range [0, 360].
private double ca = Double.NaN;
// Camera model name.
private String cameraMake;
// Date When bitmap was captured.
private Date capturedAt;
// Image key.
private String key;
// Whether the bitmap is panorama ( true ), or not ( false ).
private boolean pano;
// (optional) Which project the bitmap belongs to. Absent if it doesn't belong to any project.
private String projectKey;
// User who captured the bitmap.
private String userKey;
// Username of who captured the bitmap.
private String userName;
private static final DateFormat DATE_FORMAT = SimpleDateFormat.getDateTimeInstance(FULL, FULL, Locale.US); //"yyyy-MM-dd'T'HH:mm:ss");
private boolean downloading;
private Bitmap bitmap;
MapillaryImageInfo(JSONObject imgObj) {
try {
JSONObject props = imgObj.getJSONObject("properties");
if (props.has("ca")) {
this.ca = props.getDouble("ca");
}
if (props.has("camera_make")) {
this.cameraMake = props.getString("camera_make");
}
if (props.has("captured_at")) {
try {
this.capturedAt = DATE_FORMAT.parse(props.getString("captured_at"));
} catch (ParseException e) {
e.printStackTrace();
}
}
if (props.has("key")) {
this.key = props.getString("key");
}
if (props.has("pano")) {
this.pano = props.getBoolean("pano");
}
if (props.has("project_key")) {
this.projectKey = props.getString("project_key");
}
if (props.has("user_key")) {
this.userKey = props.getString("user_key");
}
if (props.has("username")) {
this.userName = props.getString("username");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public double getCa() {
return ca;
}
public String getCameraMake() {
return cameraMake;
}
public Date getCapturedAt() {
return capturedAt;
}
public String getKey() {
return key;
}
public boolean isPano() {
return pano;
}
public String getProjectKey() {
return projectKey;
}
public String getUserKey() {
return userKey;
}
public String getUserName() {
return userName;
}
public boolean isDownloading() {
return downloading;
}
public void setDownloading(boolean downloading) {
this.downloading = downloading;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
}

View file

@ -0,0 +1,253 @@
package net.osmand.plus.mapillary;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import net.osmand.AndroidNetworkUtils;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.util.Algorithms;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class MapillaryImageRow {
private MenuBuilder menuBuilder;
private View view;
private OsmandApplication app;
private List<MapillaryImageInfo> imageInfoList = new ArrayList<>();
private boolean updating;
private ViewsPagerAdapter pagerAdapter;
private int dp10;
public MapillaryImageRow(MenuBuilder menuBuilder, View view) {
this.menuBuilder = menuBuilder;
this.view = view;
this.app = menuBuilder.getApp();
this.dp10 = AndroidUtils.dpToPx(app, 10f);
}
public void build() {
ViewPager viewPager = new ViewPager(view.getContext());
ViewPager.LayoutParams params = new ViewPager.LayoutParams();
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = (int) app.getResources().getDimension(R.dimen.mapillary_card_height) + dp10 + dp10;
viewPager.setLayoutParams(params);
viewPager.setPageMargin(dp10);
viewPager.setPadding(dp10, dp10, dp10, dp10);
viewPager.setClipToPadding(false);
pagerAdapter = new ViewsPagerAdapter();
viewPager.setAdapter(pagerAdapter);
((LinearLayout) view).addView(viewPager);
new GetImageInfoTask().execute();
}
private void refreshScrollView() {
}
private int itemsCount() {
return updating ? 1 : imageInfoList.size() + 1;
}
private View createPageView(ViewGroup container, int position) {
View v;
if (updating && position == 0) {
v = LayoutInflater.from(view.getContext()).inflate(R.layout.mapillary_context_menu_progress, null);
} else if (position == itemsCount() - 1) {
v = LayoutInflater.from(view.getContext()).inflate(R.layout.mapillary_context_menu_action, null);
v.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// todo open mapillary
}
});
} else {
v = LayoutInflater.from(view.getContext()).inflate(R.layout.mapillary_context_menu_image, null);
ImageView image = (ImageView) v.findViewById(R.id.image);
TextView watermark = (TextView) v.findViewById(R.id.watermark);
ProgressBar progress = (ProgressBar) v.findViewById(R.id.progress);
if (position < imageInfoList.size()) {
MapillaryImageInfo info = imageInfoList.get(position);
if (info != null) {
if (Algorithms.isEmpty(info.getUserName())) {
watermark.setText("mapillary.com");
} else {
watermark.setText("@" + info.getUserName() + " | mapillary.com");
}
if (info.isDownloading()) {
progress.setVisibility(View.VISIBLE);
image.setImageBitmap(null);
} else {
progress.setVisibility(View.GONE);
image.setImageBitmap(info.getBitmap());
}
v.findViewById(R.id.image_card).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// todo open image
}
});
}
}
}
return v;
}
private class ViewsPagerAdapter extends PagerAdapter {
@Override
public float getPageWidth(int position) {
return 0.8f;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public int getCount() {
return itemsCount();
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = createPageView(container, position);
container.addView(view, 0);
return view;
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
private class GetImageInfoTask extends AsyncTask<Void, MapillaryImageInfo, Void> {
@Override
protected void onPreExecute() {
updating = true;
pagerAdapter.notifyDataSetChanged();
}
@Override
protected Void doInBackground(Void... params) {
// https://a.mapillary.com/v3/images/?lookat=12.9981086701,55.6075236275&closeto=13.0006076843,55.6089295863&radius=20&client_id=LXJVNHlDOGdMSVgxZG5mVzlHQ3ZqQTo0NjE5OWRiN2EzNTFkNDg4
try {
final Map<String, String> pms = new LinkedHashMap<>();
//pms.put("lookat", Version.getFullVersion(app));
pms.put("closeto", "" + menuBuilder.getLatLon().getLongitude() + "," + menuBuilder.getLatLon().getLatitude());
pms.put("radius", "20");
pms.put("client_id", "LXJVNHlDOGdMSVgxZG5mVzlHQ3ZqQTo0NjE5OWRiN2EzNTFkNDg4");
String response = AndroidNetworkUtils.sendRequest(app, "https://a.mapillary.com/v3/images", pms,
"Requesting mapillary images...", false, false);
if (!Algorithms.isEmpty(response)) {
JSONObject obj = new JSONObject(response);
JSONArray images = obj.getJSONArray("features");
if (images.length() > 0) {
for (int i = 0; i < images.length(); i++) {
try {
JSONObject imgObj = (JSONObject) images.get(i);
if (imgObj != JSONObject.NULL) {
MapillaryImageInfo imageInfo = new MapillaryImageInfo(imgObj);
publishProgress(imageInfo);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(MapillaryImageInfo... values) {
if (values != null && values.length > 0) {
Collections.addAll(imageInfoList, values);
}
}
@Override
protected void onPostExecute(Void aVoid) {
updating = false;
if (imageInfoList.size() > 0) {
new DownloadImagesTask().execute();
} else {
pagerAdapter.notifyDataSetChanged();
}
}
}
private class DownloadImagesTask extends AsyncTask<Void, Void, Void> {
private static final String urlTemplate = "https://d1cuyjsrcm0gby.cloudfront.net/{key}/thumb-320.jpg?origin=osmand";
@Override
protected void onPreExecute() {
for (MapillaryImageInfo imageInfo : imageInfoList) {
if (imageInfo.getBitmap() == null) {
imageInfo.setDownloading(true);
}
}
pagerAdapter.notifyDataSetChanged();
}
@Override
protected Void doInBackground(Void... params) {
for (MapillaryImageInfo imageInfo : imageInfoList) {
if (imageInfo.isDownloading()) {
String url = urlTemplate.replace("{key}", imageInfo.getKey());
Bitmap bitmap = AndroidNetworkUtils.downloadImage(app, url);
imageInfo.setBitmap(bitmap);
imageInfo.setDownloading(false);
publishProgress();
}
}
return null;
}
@Override
protected void onProgressUpdate(Void... values) {
pagerAdapter.notifyDataSetChanged();
}
@Override
protected void onPostExecute(Void aVoid) {
pagerAdapter.notifyDataSetChanged();
}
}
}

View file

@ -22,6 +22,7 @@ import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityLayers;
import net.osmand.plus.base.BottomSheetDialogFragment;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.MapTileLayer;
import net.osmand.plus.views.OsmandMapTileView;
@ -192,6 +193,22 @@ public class MapillaryPlugin extends OsmandPlugin {
}
}
@Override
public void buildContextMenuRows(@NonNull MenuBuilder menuBuilder, @NonNull View view) {
if (!menuBuilder.getApp().getSettings().isInternetConnectionAvailable()) {
return;
}
/*
if (!menuBuilder.isFirstRow()) {
menuBuilder.buildRowDivider(view, false);
}
*/
new MapillaryImageRow(menuBuilder, view).build();
//menuBuilder.rowBuilt();
}
public static class MapillaryFirstDialogFragment extends BottomSheetDialogFragment {
public static final String TAG = "MapillaryFirstDialogFragment";