Skip to content
This repository has been archived by the owner on Oct 7, 2024. It is now read-only.

Commit

Permalink
initial additions
Browse files Browse the repository at this point in the history
  • Loading branch information
langsmith committed Nov 21, 2019
1 parent 4fc8249 commit 8394569
Show file tree
Hide file tree
Showing 11 changed files with 357 additions and 3 deletions.
5 changes: 3 additions & 2 deletions MapboxAndroidDemo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ dependencies {
globalImplementation dependenciesList.firebaseCrashlytics
globalImplementation dependenciesList.firebaseCore
globalImplementation dependenciesList.firebasePerf
implementation dependenciesList.firebaseMessaging
implementation dependenciesList.firebaseRemoteConfig
implementation dependenciesList.firebaseMessaging
implementation dependenciesList.firebaseRemoteConfig
implementation dependenciesList.biometric

// Other dependencies
implementation dependenciesList.gson
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import com.mapbox.mapboxandroiddemo.examples.javaservices.TurfRingActivity;
import com.mapbox.mapboxandroiddemo.examples.labs.AnimatedImageGifActivity;
import com.mapbox.mapboxandroiddemo.examples.labs.AnimatedMarkerActivity;
import com.mapbox.mapboxandroiddemo.examples.labs.BiometricFingerprintLayerUnlockActivity;
import com.mapbox.mapboxandroiddemo.examples.labs.CalendarIntegrationActivity;
import com.mapbox.mapboxandroiddemo.examples.labs.ChangeAttributionColorActivity;
import com.mapbox.mapboxandroiddemo.examples.labs.DashedLineDirectionsPickerActivity;
Expand Down Expand Up @@ -1306,6 +1307,14 @@ private void initializeModels() {
null,
R.string.activity_lab_shared_preferences_url, true, BuildConfig.MIN_SDK_VERSION));

exampleItemModels.add(new ExampleItemModel(
R.id.nav_lab,
R.string.activity_lab_biometric_fingerprint_title,
R.string.activity_lab_biometric_fingerprint_description,
new Intent(MainActivity.this, BiometricFingerprintLayerUnlockActivity.class),
null,
R.string.activity_lab_biometric_fingerprint_url, true, BuildConfig.MIN_SDK_VERSION));

exampleItemModels.add(new ExampleItemModel(
R.id.nav_dds,
R.string.activity_dds_geojson_line_title,
Expand Down
8 changes: 8 additions & 0 deletions MapboxAndroidDemo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>

<uses-feature
android:name="android.hardware.location.gps"
Expand Down Expand Up @@ -292,6 +293,13 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="com.mapbox.mapboxandroiddemo.MainActivity" />
</activity>
<activity
android:name=".examples.labs.BiometricFingerprintLayerUnlockActivity"
android:label="@string/activity_lab_biometric_fingerprint_title">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.mapbox.mapboxandroiddemo.MainActivity" />
</activity>
<activity
android:name=".examples.labs.RecyclerViewOnMapActivity"
android:label="@string/activity_lab_rv_on_map_title">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
package com.mapbox.mapboxandroiddemo.examples.labs;

import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.Toast;

import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.biometric.BiometricManager;
import androidx.biometric.BiometricPrompt;

import static androidx.biometric.BiometricConstants.ERROR_NEGATIVE_BUTTON;
import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_BOTTOM;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAnchor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;

/**
* Integrate the Maps SDK with the Android-system biometric unlock system. Use a saved fingerprint to
* add data to the map once the user is verified.
*/
public class BiometricFingerprintLayerUnlockActivity extends AppCompatActivity {

private static final String SOURCE_ID = "SOURCE_ID";
private static final String ICON_ID = "ICON_ID";
private static final String LAYER_ID = "LAYER_ID";
private MapView mapView;
private MapboxMap mapboxMap;
private BiometricPrompt biometricPrompt;
private Executor executor = Executors.newSingleThreadExecutor();

/**
* Authentication callback used after the biometric authentication process is run
*/
private BiometricPrompt.AuthenticationCallback callback = new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
if (errorCode == ERROR_NEGATIVE_BUTTON && biometricPrompt != null) {
biometricPrompt.cancelAuthentication();
}
runOnUiThread(() -> Toast.makeText(BiometricFingerprintLayerUnlockActivity.this,
errString.toString(), Toast.LENGTH_SHORT).show());
}

@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
runOnUiThread(new Runnable() {
public void run() {
mapboxMap.getStyle(new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {

style.addImage(ICON_ID, BitmapFactory.decodeResource(
BiometricFingerprintLayerUnlockActivity.this.getResources(), R.drawable.red_marker));

// Adding a GeoJSON source for the SymbolLayer icons.
style.addSource(new GeoJsonSource(SOURCE_ID,
FeatureCollection.fromFeatures(initFeaturePointList())));

// Adding the actual SymbolLayer to the map style. An offset is added that the bottom of the red
// marker icon gets fixed to the coordinate, rather than the middle of the icon being fixed to
// the coordinate point. This is offset is not always needed and is dependent on the image
// that you use for the SymbolLayer icon.
style.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
.withProperties(
iconImage(ICON_ID),
iconAllowOverlap(true),
iconIgnorePlacement(true),
iconAnchor(ICON_ANCHOR_BOTTOM)));
}
});
}
});
}

@Override
public void onAuthenticationFailed() {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(BiometricFingerprintLayerUnlockActivity.this, R.string.fingerprint_fail,
Toast.LENGTH_SHORT).show();
}
});
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Mapbox access token is configured here. This needs to be called either in your application
// object or in the same activity which contains the mapview.
Mapbox.getInstance(this, getString(R.string.access_token));

// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_labs_biometric_fingerprint);

mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull final MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.SATELLITE_STREETS, new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {
BiometricFingerprintLayerUnlockActivity.this.mapboxMap = mapboxMap;
if (isFingerprintAvailable()) {
if (biometricPrompt == null) {
biometricPrompt = new BiometricPrompt(
BiometricFingerprintLayerUnlockActivity.this, executor, callback);
}
biometricPrompt.authenticate(buildBiometricPrompt());
} else {
Toast.makeText(BiometricFingerprintLayerUnlockActivity.this, R.string.fingerprint_not_possible,
Toast.LENGTH_SHORT).show();
}
}
});
}
});
}

/**
* Check whether the a fingerprint can be authenticated by the particular device. There's a chance that the device
* doesn't have a fingerprint sensor and/or the user's fingerprint hasn't been set up yet in the device's settings.
*
* @return boolean about whether the device supports fingerprint authentication.
*/
private boolean isFingerprintAvailable() {
return BiometricManager.from(BiometricFingerprintLayerUnlockActivity.this).canAuthenticate()
== BiometricManager.BIOMETRIC_SUCCESS;
}

/**
* Build a {@link BiometricPrompt} to provide information and instruct the user to use a thumbprint to display
* data on the map.
*
* @return a built {@link BiometricPrompt.PromptInfo} object to authenticate.
*/
private BiometricPrompt.PromptInfo buildBiometricPrompt() {
return new BiometricPrompt.PromptInfo.Builder()
.setTitle(getString(R.string.prompt_title))
.setSubtitle(getString(R.string.prompt_subtitle))
.setDescription(getString(R.string.prompt_description))
.setNegativeButtonText(getString(R.string.prompt_negative_button))
.build();
}

@Override
public void onResume() {
super.onResume();
mapView.onResume();
}

@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}

@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}

@Override
public void onPause() {
super.onPause();
mapView.onPause();
}

@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}

@Override
protected void onDestroy() {
super.onDestroy();
if (biometricPrompt != null) {
biometricPrompt.cancelAuthentication();
}
mapView.onDestroy();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}

private List<Feature> initFeaturePointList() {
List<Feature> symbolLayerIconFeatureList = new ArrayList<>();
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
66.298729,
42.928145)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
77.28305,
39.854244)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
61.544321,
46.026979)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
57.691611,
36.108244)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
53.756929,
32.797029)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
80.725897,
42.203685)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
76.217407,
44.876952)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
72.77456,
38.584169)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
74.414011,
31.687743)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
64.659278,
47.153569)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
70.807219,
46.649501)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
76.053462,
49.973477)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
68.757905,
43.940044)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
68.757905,
30.776557)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
59.740925,
29.714372)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
66.216756,
34.772613)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
64.659278,
50.497793)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
70.561301,
52.137028)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
54.576655,
49.443387)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
65.233086,
38.263068)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
80.561952,
48.202166)));
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(
58.593309,
41.101246)));
return symbolLayerIconFeatureList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.List;

import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;

/**
Expand Down Expand Up @@ -79,6 +80,7 @@ public void onMapReady(@NonNull final MapboxMap mapboxMap) {
.withLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
.withProperties(PropertyFactory.iconImage(ICON_ID),
iconAllowOverlap(true),
iconIgnorePlacement(true),
iconOffset(new Float[] {0f, -9f}))
), new Style.OnStyleLoaded() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".examples.labs.BiometricFingerprintLayerUnlockActivity">

<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:mapbox_cameraTargetLat="37.755"
mapbox:mapbox_cameraTargetLng="71.330"
mapbox:mapbox_cameraZoom="3.31" />

</FrameLayout>
Loading

0 comments on commit 8394569

Please sign in to comment.