Display multiple routes in mapbox - mapbox-android

I am trying to display multiple routes in mapbox,I also enabled alternative to true still multiple routes are not displayed,would like to plot multiple routes on a map. However, this is not working.Is there any ways to display multiple routes in mapbox?
I also attached my code below.
private void getRoute(MapboxMap mapboxMap, Point origin, Point destination) {
client = MapboxDirections.builder()
.origin(origin)
.destination(destination)
.overview(DirectionsCriteria.OVERVIEW_FULL)
.profile(DirectionsCriteria.PROFILE_DRIVING)
.accessToken(getString(R.string.mapbox_access_token))
.alternatives(true)
.build();
client.enqueueCall(new Callback<DirectionsResponse>() {
#Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
// You can get the generic HTTP info about the response
Timber.d("Response code: " + response.code());
if (response.body() == null) {
Timber.e("No routes found, make sure you set the right user and access token.");
return;
} else if (response.body().routes().size() < 1) {
Timber.e("No routes found");
return;
}
// Get the directions route
currentRoute = response.body().routes().get(0);
// Make a toast which displays the route's distance
Toast.makeText(DirectionsActivity.this, String.format(
"directions_activity_toast_message"), Toast.LENGTH_SHORT).show();
if (mapboxMap != null) {
mapboxMap.getStyle(new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
// Retrieve and update the source designated for showing the directions route
GeoJsonSource source = style.getSourceAs(ROUTE_SOURCE_ID);
// Create a LineString with the directions route's geometry and
// reset the GeoJSON source for the route LineLayer source
if (source != null) {
source.setGeoJson(LineString.fromPolyline(currentRoute.geometry(), PRECISION_6));
}
}
});
}
}

Related

Using dynamic preloaded image in Flutter/Dart

I currently have images which the image name is returned by a function and is dynamically called based on a variable like this:
String _setImage() {
if (currentQuestion > 1 && currentQuestion < 11) {
return "assets/images/image_$intensityIndex.png";
} else {
return "assets/images/image.png";
}
}
I want to switch to preloading the images and I am using the technique described at Preload images in a stateful widget on Flutter, but I am not sure how to have the function return an image which the name is dynamically determined based on another variable. Here is what I have so far:
void initState() {
super.initState();
image0 = Image.asset('assets/images/image_0.png');
image1 = Image.asset('assets/images/image_1.png');
image2 = Image.asset('assets/images/image_2.png');
image3 = Image.asset('assets/images/image_3.png');
}
void didChangeDependencies() {
super.didChangeDependencies();
precacheImage(image0.image, context);
precacheImage(image1.image, context);
precacheImage(image2.image, context);
precacheImage(image3.image, context);
}
Image _setImage() {
if (currentQuestion > 1 && currentQuestion < 11) {
return ______________;
} else {
return image0;
}
}
All help is appreciated!
Am not sure how to return an image which the name is dynamically
determined based on another variable
You don't need to return with precach because if you use exact image that you cache.
Ex:
precacheImage('assets/images/image_1.png'); // if this is the image name
Image.asset('assets/images/image_1.png'); // when you use this it is getting from the cache but the path should be same.
If I explain it another way:
precacheImage("assets/images/image_$intensityIndex.png"); // image_1.png
Image.asset('assets/images/image_1.png'); // when you do this, asset taking from the cache by looking at the path.

How to implement Play Install Referrer API in Android?

I want to implement Play Install Referrer API and I found document and I read that but I have have some confusion. First I have implemented all code provided by google. But I want to know which type of url I need to create so that user can click on link and go to play store and install my app and then I get the referral detail..
I use this code:
InstallReferrerClient mReferrerClient;
mReferrerClient = newBuilder(this).build();
mReferrerClient.startConnection(this);
#Override
public void onInstallReferrerSetupFinished ( int responseCode){
switch (responseCode) {
case InstallReferrerClient.InstallReferrerResponse.OK:
// Connection established
/* ReferrerDetails response = null;
try {
response = mReferrerClient.getInstallReferrer();
response.getInstallReferrer();
response.getReferrerClickTimestampSeconds();
response.getInstallBeginTimestampSeconds();
} catch (RemoteException e) {
e.printStackTrace();
}*/
break;
case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
// API not available on the current Play Store app
break;
case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
// Connection could not be established
break;
}
}
#Override
public void onInstallReferrerServiceDisconnected () {
}
But which type of link I create so user go to play store and after install play store referral api give me data..
Sample url - "https://play.google.com/store/apps/details?id=com.dummy.app&referrer=referralCode%3D311566%26source%3DFacebook+App"
When using the Google Play Referrer API -
InstallReferrerClient mReferrerClient;
mReferrerClient = newBuilder(this).build();
mReferrerClient.startConnection(this);
#Override
public void onInstallReferrerSetupFinished ( int responseCode){
switch (responseCode) {
case InstallReferrerClient.InstallReferrerResponse.OK:
// Connection established
/* ReferrerDetails response = null;
try {
response = mReferrerClient.getInstallReferrer();
response.getInstallReferrer();
response.getReferrerClickTimestampSeconds();
response.getInstallBeginTimestampSeconds();
} catch (RemoteException e) {
e.printStackTrace();
}*/
// End the connection once you get the data
referrerClient.endConnection();
break;
case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
// API not available on the current Play Store app
break;
case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
// Connection could not be established
break;
}
}
#Override
public void onInstallReferrerServiceDisconnected () {
}
getInstallReferrer()
will return String 'referralCode=311566&source=Facebook App'
play install referral library i wants to describe this in simple wording, being a developer you wants to know about these elements how much time you app bundle take to install on the user devices from play store, and referral url , referral click time and many others elements , google make it easy for you know you have to use play install referral library for this purpose.
add this dependency
implementation 'com.android.installreferrer:installreferrer:1.1'
you can follow the guidelines from here:
play installer referral guidelines
declare this variable in any java activity
InstallReferrerClient referrerClient;
in on create method use this code below :
referrerClient = InstallReferrerClient.newBuilder(this).build();
referrerClient.startConnection(new InstallReferrerStateListener() {
#Override
public void onInstallReferrerSetupFinished(int responseCode) {
switch (responseCode) {
case InstallReferrerClient.InstallReferrerResponse.OK:
// Connection established.
break;
case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
// API not available on the current Play Store app.
break;
case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
// Connection couldn't be established.
break;
}
}
#Override
public void onInstallReferrerServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
inside onInstallReferrerSetupFinished stabled you can get these data easily,you code will be after that like this
ReferrerDetails response = null;
try {
response = referrerClient.getInstallReferrer();
} catch (RemoteException e) {
e.printStackTrace();
}
String referrerUrl = response.getInstallReferrer();
long referrerClickTime = response.getReferrerClickTimestampSeconds();
long appInstallTime = response.getInstallBeginTimestampSeconds();
boolean instantExperienceLaunched = response.getGooglePlayInstantParam();
whole code will be like this
referrerClient = InstallReferrerClient.newBuilder(this).build();
referrerClient.startConnection(new InstallReferrerStateListener() {
#Override
public void onInstallReferrerSetupFinished(int responseCode) {
switch (responseCode) {
case InstallReferrerClient.InstallReferrerResponse.OK:
// Connection established.
ReferrerDetails response = null;
try {
response = referrerClient.getInstallReferrer();
} catch (RemoteException e) {
e.printStackTrace();
}
String referrerUrl = response.getInstallReferrer();
long referrerClickTime = response.getReferrerClickTimestampSeconds();
long appInstallTime = response.getInstallBeginTimestampSeconds();
boolean instantExperienceLaunched = response.getGooglePlayInstantParam();
break;
case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
// API not available on the current Play Store app.
break;
case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
// Connection couldn't be established.
break;
}
}
#Override
public void onInstallReferrerServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});

TornadoFX Drag and Drop on a TreeView

I am new to JavaFX and, therefore, also to TornadoFX so please bear with me.
I have a simple app in Java but want to move it to Kotlin and am running into problems finding the corresponding mechanisms in TornadoFX. I have a ListView holding implementations of IStoryItem representing Stories and Chapters. I want to be able to move the chapters around and even from one story to another. The TreeView in Java has the following implementation in its setCellFactory call:
tv.setCellFactory(new Callback<TreeView<IStoryItem>, TreeCell<IStoryItem>>() {
#Override
public TreeCell<IStoryItem> call(TreeView<IStoryItem> siTreeView) {
TreeCell<IStoryItem> cell = new TreeCellStoryEditor();
cell.setOnDragDetected((MouseEvent event) -> {
// Don't drag Story nodes.
if (cell.getItem() instanceof Story) return;
Dragboard db = cell.startDragAndDrop(TransferMode.MOVE);
// Put the Part on the dragboard
// From: https://stackoverflow.com/a/30916660/780350
ClipboardContent content = new ClipboardContent();
content.put(objectDataFormat, cell.getItem());
db.setContent(content);
event.consume();
});
cell.setOnDragOver((DragEvent event) -> {
if (event.getGestureSource() != cell && event.getDragboard().hasContent(objectDataFormat)) {
/* allow for moving */
event.acceptTransferModes(TransferMode.MOVE);
}
event.consume();
});
cell.setOnDragEntered((DragEvent event) -> {
IStoryItem item = cell.getItem();
if (item instanceof Story &&
event.getGestureSource() != cell &&
event.getDragboard().hasContent(objectDataFormat)) {
cell.setUnderline(true);
}
event.consume();
});
cell.setOnDragExited((DragEvent event) -> {
cell.setUnderline(false);
event.consume();
});
cell.setOnDragDropped((DragEvent event) -> {
try {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasContent(objectDataFormat)) {
Part droppedPart = (Part)db.getContent(objectDataFormat);
IStoryItem targetStoryItem = cell.getItem();
// Question: How to handle drops between leaf items or
// before the initial leaf or after the final leaf.
if (targetStoryItem instanceof Story) {
Story story = (Story) targetStoryItem;
updateStoryWith(droppedPart, story);
addPartTo(cell.getTreeItem(), droppedPart);
success = true;
}
}
event.setDropCompleted(success);
event.consume();
} catch (Exception e) {
System.out.println(e.getMessage());
}
});
cell.setOnDragDone((DragEvent event) -> {
if (event.getTransferMode() == TransferMode.MOVE) {
IStoryItem item = cell.getItem();
TreeItem<IStoryItem> ti = cell.getTreeItem();
TreeItem<IStoryItem> pti = ti.getParent();
pti.getChildren().remove(ti);
IStoryItem psi = pti.getValue();
// Remove the Part/Chapter from its previous Story
boolean removed = removePartFrom(psi, item);
}
event.consume();
});
cell.setEditable(true);
return cell;
};
});
I have looked for something similar in TornadoFX but can't find anything that looks like it would work. I am already using the cellFormat builder but I can't figure out how to add the event handlers inside it. I see from IntelliJ's intellisense that there is also a cellFactory builder but I am not sure how to make use of it or how to add the event handlers to it.
You can use the exact same technique in TornadoFX. Remember, TornadoFX just applies a high level API on top of JavaFX. You can always still access the underlying JavaFX API's without issue.
tv.setCellFactory {
object : TreeCell<IStoryItem>() {
init {
setOnDragOver { event ->
}
setOnDragEntered { event ->
}
setOnDragExited { event ->
}
setOnDragDropped { event ->
}
}
}
}

Android crop intent doesn't work on system gallery app but works on 3rd-party app

I try to pick an image from sdcard and then crop it.
ACTION_PICK is OK, but when i call ACTION_CROP, my system gallery app (I call it as A) can't done the action, but another app (B) can.
I tried the following cases:
1/ Pick by A and then crop by A => pick OK, crop fail
2/ Pick by B and then crop by A => the same as first case.
3/ Pick by A and then crop by B => every things OK.
4/ Pick by B and then crop by B => every things OK.
So my temporary conclusion is: my system app can't do the crop action with my code (may be i forgot something). Here is my code:
ACTION_PICK:
public Intent galleryIntent() {
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
galleryIntent.putExtra("return-data", true);
return galleryIntent;
}
ACTION_CROP:
public Intent cropIntent(Uri inUri, int outputX, int outputY,
boolean isScale) {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(inUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", outputX);
cropIntent.putExtra("aspectY", outputY);
cropIntent.putExtra("outputX", outputX);
cropIntent.putExtra("outputY", outputY);
cropIntent.putExtra("scale", isScale);
cropIntent.putExtra("return-data", true);
return cropIntent;
}
My onActivityResult method
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_CODE_GALLERY:
imageUri = data.getData();
startActivityForResult(cropIntent(imageUri,
500, 500, true), REQUEST_CODE_CROP);
break;
case REQUEST_CODE_CROP:
Bundle extras = data.getExtras();
Bitmap tempBitmap = extras.getParcelable("data");
imgvMain.setImageBitmap(null);
imgvMain.setImageBitmap(tempBitmap);
break;
}
} else {
imageUri = null;
}
}
Am i missing somethings?
Thank for your attention!
I use this code successfully for Android 2.2 and up:
It opens a selection of apps that can get image files e.g. the Gallery app. If the selected app can crop, it will also do so.
The cropped image will be saved to the supplied temp file.
(note the small difference for KITKAT).
Intent intent = new Intent();
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("outputX", Constants.IMAGE_WIDTH);
intent.putExtra("outputY", Constants.IMAGE_HEIGHT);
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("scale", true);
intent.putExtra("scaleUpIfNeeded", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(<a temp file created somewhere>));
intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
{
intent.setAction(Intent.ACTION_GET_CONTENT);
}
else
{
intent.setAction(Intent.ACTION_PICK);
intent.setData(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
startActivityForResult(intent, RESULT_CROP);
EDIT:
I ended up using custom cropping using: https://github.com/biokys/cropimage. It was very easy and I had no more troubles with cropping :-)
I checked the logs by filtering with gallery3d and found out that the stock app is not getting permission to access the uri. Hence it's behaving unexpectedly. That behaviour is different for different platforms.
Solution:
get the uri of the selected image in onActivityResult() for intent ACTION_PICK.
save the image temporarily.
create new URI from the saved image.
pass the new URI to com.android.camera.action.CROP.
Sample code: (Dont copy paste. for simplicity ,I have removed the error checks and async tasks.)
public void pickCroppedPhoto(){
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra("crop", "true");
populateCropExtras(activity, photoPickerIntent);
startActivityForResult(photoPickerIntent , REQUEST_CODE_PICK);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
if (requestCode == REQUEST_CODE_PICK ) {
File mainImage = saveUriInFile( this,
data.getData(),
getTempFileForMainImage());
if (null == mainImage) {
handleImageSelectionFailure();
}else {
try {
Uri mainFileUri = Uri.fromFile(mainImage);
performCrop(this,mainFileUri);
}catch(Exception e){
handleImageSelectionFailure();
}
}
}else if ( requestCode == PIC_CROP ){
postImageSelection(data.getData());
}
}
Here is my performCrop code which is similar to that of the question.
public static boolean performCrop(Activity activity, Uri picUri) {
try {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
// indicate image type and Uri
cropIntent.setDataAndType(picUri, "image/*");
if (populateCropExtras(activity, cropIntent)) return false;
activity.startActivityForResult(cropIntent, PIC_CROP);
return true;
}
// respond to users whose devices do not support the crop action
catch (ActivityNotFoundException anfe) {
String errorMessage = "Device doesn't support crop!";
Log.w(PhotoPickerUtil.class.getCanonicalName(), errorMessage);
return false;
}catch (IOException ioe){
String errorMessage = "Error while getting temporary file from external storage";
Log.w(PhotoPickerUtil.class.getCanonicalName(), errorMessage);
return false;
}
}
private static void populateCropExtras(Activity activity, Intent cropIntent) throws IOException { {
// set crop properties
cropIntent.putExtra("crop", "true");
// indicate output X and Y
cropIntent.putExtra("outputX", 300);
cropIntent.putExtra("outputY", 300);
// indicate aspect of desired crop
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
cropIntent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
Uri tempUri = Uri.fromFile(getTempFile(activity));
cropIntent.putExtra("output", tempUri);
}

MVVM - View loading and eventhandling

In my windows phone app, I need to track some events to get a good flow. But I'm not sure how to handle them in good sequence.
What needs to be done at startup of the app:
Main view is loaded and corresponding view model instantiated
In the constructor of the view model I initiate a login sequence that signals when completed with an eventhandler
Now when the login sequence has finished AND the view is completely loaded I need to startup another sequence.
But here is the problem, the order of these 2 events 'completing' is not always the same...
I've use the EventToCommand from MVVMLight to signal the view model that the view has 'loaded'.
Any thoughts on how to synchronize this.
As you should not use wait handles or something similar on the UI thread. You will have to sync the two method using flags in your view model and check them before progressing.
So, implement two boolean properties in your view model. Now when the login dialog is finished set one of the properties (lets call it IsLoggedIn) to true, and when the initialization sequence is finished you set the other property (how about IsInitialized) to true. The trick now lies in the implementation of the setter of these two properties:
#region [IsInitialized]
public const string IsInitializedPropertyName = "IsInitialized";
private bool _isInitialized = false;
public bool IsInitialized {
get {
return _isInitialized;
}
set {
if (_isInitialized == value)
return;
var oldValue = _isInitialized;
_isInitialized = value;
RaisePropertyChanged(IsInitializedPropertyName);
InitializationComplete();
}
}
#endregion
#region [IsLoggedIn]
public const string IsLoggedInPropertyName = "IsLoggedIn";
private bool _isLoggedIn = false;
public bool IsLoggedIn {
get {
return _isLoggedIn;
}
set {
if (_isLoggedIn == value)
return;
var oldValue = _isLoggedIn;
_isLoggedIn = value;
RaisePropertyChanged(IsLoggedInPropertyName);
InitializationComplete();
}
}
#endregion
public void InitializationComplete() {
if (!(this.IsInitialized && this.IsLoggedIn))
return;
// put your code here
}
Alternatively you can remove the InitializationComplete from the setters and change InitializationComplete to:
public void InitializationComplete() {
// put your code here
}
Then subscribe to the 'PropertyChanged' event use the following implementation:
private void Class1_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
if (e.PropertyName == IsInitializedPropertyName || e.PropertyName == IsLoggedInPropertyName) {
if (this.IsInitialized && this.IsLoggedIn)
InitializationComplete();
}
}

Resources