This repository has been archived by the owner on Aug 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[android] - derived source attribution (#8630)
- Loading branch information
Showing
9 changed files
with
278 additions
and
120 deletions.
There are no files selected for viewing
169 changes: 169 additions & 0 deletions
169
.../MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package com.mapbox.mapboxsdk.maps; | ||
|
||
import android.content.Context; | ||
import android.content.DialogInterface; | ||
import android.content.Intent; | ||
import android.net.Uri; | ||
import android.support.annotation.NonNull; | ||
import android.support.v7.app.AlertDialog; | ||
import android.text.Html; | ||
import android.text.SpannableStringBuilder; | ||
import android.text.TextUtils; | ||
import android.text.style.URLSpan; | ||
import android.view.View; | ||
import android.widget.ArrayAdapter; | ||
|
||
import com.mapbox.mapboxsdk.R; | ||
import com.mapbox.mapboxsdk.camera.CameraPosition; | ||
import com.mapbox.mapboxsdk.style.sources.Source; | ||
import com.mapbox.services.android.telemetry.MapboxTelemetry; | ||
|
||
import java.util.HashMap; | ||
import java.util.LinkedHashMap; | ||
import java.util.Locale; | ||
|
||
/** | ||
* Responsible for managing attribution interactions on the map. | ||
* <p> | ||
* When the user clicks the attribution icon, {@link AttributionDialogManager#onClick(View)} will be invoked. | ||
* An attribution dialog will be shown to the user with contents based on the attributions found in the map style. | ||
* Additionally an telemetry option item is shown to configure telemetry settings. | ||
* </p> | ||
*/ | ||
class AttributionDialogManager implements View.OnClickListener, DialogInterface.OnClickListener { | ||
|
||
private static final String MAP_FEEDBACK_URL = "https://www.mapbox.com/map-feedback"; | ||
private static final String MAP_FEEDBACK_LOCATION_FORMAT = MAP_FEEDBACK_URL + "/#/%f/%f/%d"; | ||
|
||
private final Context context; | ||
private final MapboxMap mapboxMap; | ||
private String[] attributionKeys; | ||
private HashMap<String, String> attributionMap; | ||
|
||
AttributionDialogManager(@NonNull Context context, @NonNull MapboxMap mapboxMap) { | ||
this.context = context; | ||
this.mapboxMap = mapboxMap; | ||
} | ||
|
||
// Called when someone presses the attribution icon on the map | ||
@Override | ||
public void onClick(View view) { | ||
attributionMap = new AttributionBuilder(context, mapboxMap).build(); | ||
showAttributionDialog(); | ||
} | ||
|
||
private void showAttributionDialog() { | ||
attributionKeys = attributionMap.keySet().toArray(new String[attributionMap.size()]); | ||
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.mapbox_AlertDialogStyle); | ||
builder.setTitle(R.string.mapbox_attributionsDialogTitle); | ||
builder.setAdapter(new ArrayAdapter<>(context, R.layout.mapbox_attribution_list_item, attributionKeys), this); | ||
builder.show(); | ||
} | ||
|
||
// Called when someone selects an attribution or telemetry settings from the dialog | ||
@Override | ||
public void onClick(DialogInterface dialog, int which) { | ||
if (isLatestEntry(which)) { | ||
showTelemetryDialog(); | ||
} else { | ||
showAttributionWebPage(which); | ||
} | ||
} | ||
|
||
private boolean isLatestEntry(int attributionKeyIndex) { | ||
return attributionKeyIndex == attributionKeys.length - 1; | ||
} | ||
|
||
private void showTelemetryDialog() { | ||
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.mapbox_AlertDialogStyle); | ||
builder.setTitle(R.string.mapbox_attributionTelemetryTitle); | ||
builder.setMessage(R.string.mapbox_attributionTelemetryMessage); | ||
builder.setPositiveButton(R.string.mapbox_attributionTelemetryPositive, new DialogInterface.OnClickListener() { | ||
@Override | ||
public void onClick(DialogInterface dialog, int which) { | ||
MapboxTelemetry.getInstance().setTelemetryEnabled(true); | ||
dialog.cancel(); | ||
} | ||
}); | ||
builder.setNeutralButton(R.string.mapbox_attributionTelemetryNeutral, new DialogInterface.OnClickListener() { | ||
@Override | ||
public void onClick(DialogInterface dialog, int which) { | ||
String url = context.getResources().getString(R.string.mapbox_telemetryLink); | ||
Intent intent = new Intent(Intent.ACTION_VIEW); | ||
intent.setData(Uri.parse(url)); | ||
context.startActivity(intent); | ||
dialog.cancel(); | ||
} | ||
}); | ||
builder.setNegativeButton(R.string.mapbox_attributionTelemetryNegative, new DialogInterface.OnClickListener() { | ||
@Override | ||
public void onClick(DialogInterface dialog, int which) { | ||
MapboxTelemetry.getInstance().setTelemetryEnabled(false); | ||
dialog.cancel(); | ||
} | ||
}); | ||
builder.show(); | ||
} | ||
|
||
private void showAttributionWebPage(int which) { | ||
Intent intent = new Intent(Intent.ACTION_VIEW); | ||
String url = attributionMap.get(attributionKeys[which]); | ||
if (url.contains(MAP_FEEDBACK_URL)) { | ||
url = buildMapFeedbackMapUrl(mapboxMap.getCameraPosition()); | ||
} | ||
intent.setData(Uri.parse(url)); | ||
context.startActivity(intent); | ||
} | ||
|
||
private String buildMapFeedbackMapUrl(CameraPosition cameraPosition) { | ||
// appends current location to the map feedback url if available | ||
return cameraPosition != null ? String.format(Locale.getDefault(), | ||
MAP_FEEDBACK_LOCATION_FORMAT, cameraPosition.target.getLongitude(), cameraPosition.target.getLatitude(), | ||
(int) cameraPosition.zoom) : MAP_FEEDBACK_URL; | ||
} | ||
|
||
private static class AttributionBuilder { | ||
|
||
private final HashMap<String, String> map = new LinkedHashMap<>(); | ||
private final Context context; | ||
private final MapboxMap mapboxMap; | ||
|
||
AttributionBuilder(Context context, MapboxMap mapboxMap) { | ||
this.context = context.getApplicationContext(); | ||
this.mapboxMap = mapboxMap; | ||
} | ||
|
||
private HashMap<String, String> build() { | ||
for (Source source : mapboxMap.getSources()) { | ||
parseAttribution(source.getAttribution()); | ||
} | ||
addTelemetryEntryToAttributionMap(); | ||
return map; | ||
} | ||
|
||
private void parseAttribution(String attributionSource) { | ||
if (!TextUtils.isEmpty(attributionSource)) { | ||
SpannableStringBuilder htmlBuilder = (SpannableStringBuilder) Html.fromHtml(attributionSource); | ||
URLSpan[] urlSpans = htmlBuilder.getSpans(0, htmlBuilder.length(), URLSpan.class); | ||
for (URLSpan urlSpan : urlSpans) { | ||
map.put(resolveAnchorValue(htmlBuilder, urlSpan), urlSpan.getURL()); | ||
} | ||
} | ||
} | ||
|
||
private String resolveAnchorValue(SpannableStringBuilder htmlBuilder, URLSpan urlSpan) { | ||
int start = htmlBuilder.getSpanStart(urlSpan); | ||
int end = htmlBuilder.getSpanEnd(urlSpan); | ||
int length = end - start; | ||
char[] charKey = new char[length]; | ||
htmlBuilder.getChars(start, end, charKey, 0); | ||
return String.valueOf(charKey); | ||
} | ||
|
||
private void addTelemetryEntryToAttributionMap() { | ||
String telemetryKey = context.getString(R.string.mapbox_telemetrySettings); | ||
String telemetryLink = context.getString(R.string.mapbox_telemetryLink); | ||
map.put(telemetryKey, telemetryLink); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 0 additions & 16 deletions
16
platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.