Xamarin Custom Map Pin Renderers - c#

Firstly I would like to disclose that I am a new developer and just starting out coding with Xamarin and C sharp.
Ok. So I am creating a custom renderer for the map pin in my application. I have been using the following sample code found here: https://github.com/xamarin/xamarin-forms-samples/tree/master/CustomRenderers/Map/Pin
As it currently stands I am trying to set the popup on the pins so that when I click on them they will either go to a page in the app or possibly have a popup come up with more details on that specific pin location. Currently when I click on the pin popup it takes me to a website.
Here is a screen shot of the app:
enter image description here
I have been looking at this code and Im trying to figure out if it would be possible to change the URL to a local page?
InitializeComponent();
var position1 = new Position(52.649005, -7.250712);
var position2 = new Position(52.648061, -7.252879);
var position3 = new Position(52.650519, -7.249260);
var position4 = new Position(52.652680, -7.244724);
var position5 = new Position(52.648061, -7.252879);
var position6 = new Position(52.648061, -7.252879);
var pin1 = new CustomPin
{
Type = PinType.Place,
Position = position1,
Label = "Butler House",
Address = "394 Pacific Ave, San Francisco CA",
Id = "test",
Url = "http://xamarin.com/about/"
};
var pin2 = new CustomPin
{
Type = PinType.Place,
Position = position2,
Label = "Talbots Tower",
Address = "394 Pacific Ave, San Francisco CA",
Id = "",
Url = "http://xamarin.com/about/"
};
In the CustomMapRender.cs file here is where I believe I need to be able to alter the CustomPin.URL to allow me to click and get local pages in the app itself.
protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
{
MKAnnotationView annotationView = null;
if (annotation is MKUserLocation)
return null;
var customPin = GetCustomPin(annotation as MKPointAnnotation);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
annotationView = mapView.DequeueReusableAnnotation(customPin.Id.ToString());
if (annotationView == null)
{
annotationView = new CustomMKAnnotationView(annotation, customPin.Id.ToString());
annotationView.Image = UIImage.FromFile("pin-red-10.png"); //pin is set by image not changable by colour attributes
annotationView.CalloutOffset = new CGPoint(0, 0);
annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("Ireland-icon.png"));
annotationView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
((CustomMKAnnotationView)annotationView).Id = customPin.Id.ToString();
((CustomMKAnnotationView)annotationView).Url = customPin.Url;
}
annotationView.CanShowCallout = true;
return annotationView;
Any help or insight on this would be much appreciated as Im going around in circles trying so many different things at present.
Thanks
Michael

GetViewForAnnotation method is for getting the MKAnnotationView (i.e., the callout that's displaying the details of the Pin).
What you need is the tap event of the MKMapView callout. Add an EventHandler to CalloutAccessoryControlTapped and handle the logic for navigation.
In the sample provided it would be this part
void OnCalloutAccessoryControlTapped(object sender, MKMapViewAccessoryTappedEventArgs e)
{
// handle navigation here instead of opening the webpage
var customView = e.View as CustomMKAnnotationView;
if (!string.IsNullOrWhiteSpace(customView.Url))
{
UIApplication.SharedApplication.OpenUrl(new Foundation.NSUrl(customView.Url));
}
}

Related

How to use Adaptive Cards on Teams Messaging Extension?

I'm developing a Teams Message Extension and I'm using ThumbnailCard to display my results, however I wanted to use a custom adaptive card. Is that possible?
var resultCardList = GetAttachments(title);
var response = new ComposeExtensionResponse(new ComposeExtensionResult("list", "result"));
response.ComposeExtension.Attachments = resultCardList.ToList();
return response;
foreach (var contract in contractItems)
{
var lastModified = (DateTime)contract["Modified"];
var justificativa = contract["JustificativaContrato"];
var card = new ThumbnailCard
{
Title = $"{contract.Client_Title} - {lastModified.ToShortDateString()} {lastModified.ToLongTimeString()}",
Text = $"Justificativa: {justificativa}",
Tap = new CardAction { Type = "openUrl", Value = $"{Tenant}{ContractList.DefaultEditFormUrl}?ID={contract.Id}" },
Images = new List<CardImage> { new CardImage("http://lorempixel.com/640/480?rand=" + DateTime.Now.Ticks.ToString()) }
};
cardList.Add(card
.ToAttachment()
.ToComposeExtensionAttachment());
}
return cardList;
I've tried to use the below method to generate the Adaptive Card and just add it to the list:
private static Microsoft.Bot.Connector.Attachment CreateAdaptiveCardAttachment()
{
// combine path for cross platform support
string[] paths = { ".", "Cards", "welcomeCard.json" };
string fullPath = Path.Combine(paths);
var adaptiveCard = System.IO.File.ReadAllText(#"Cards\welcomeCard.json");
return new Microsoft.Bot.Connector.Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(adaptiveCard),
};
}
The messaging extension does not allow sending adaptive cards like that.
It requires using the "MessagingExtensionResult" of the framework and just the card sent in the response. The documentation is a bit lacking here.
When you get a call from the messaging extension its action is of type "composeExtension/query"
Create the general "result" list like this:
var invokeResponse = new MessagingExtensionResponse();
var results = new MessagingExtensionResult
{
AttachmentLayout = "list",
Type = "result",
Attachments = new List<MessagingExtensionAttachment>(),
};
For each result in the list you need to create a MessagingExtensionAttachment like this: (Note: Cards need to have a preview!)
results.Attachments.Add(new MessagingExtensionAttachment
{
ContentType = "application/vnd.microsoft.teams.card.adaptive",
Content = JsonConvert.DeserializeObject(cardData),
Preview = new Attachment
{
ContentType = "application/vnd.microsoft.card.thumbnail",
Content = new AttachmentContent
{
text = "Project: " + task.ProjectName,
title = task.Name,
},
}
});
Finally send the result as "InvokeResponse"
return new InvokeResponse
{
Body = invokeResponse,
Status = 200,
};
While "content" of the attachment is the full adaptive card.
You can find an example for the response in json here:
https://learn.microsoft.com/de-de/microsoftteams/platform/concepts/messaging-extensions/search-extensions#response-example
You can freely mix card types based on that, but i never got that working tho...as of now you need to limit to one specific card type as far as i know.
All above is if you're using
Microsoft.Bot.Builder.Teams
Microsoft.Bot.Connector.Teams
Microsoft.Bot.Schema.Teams
in the latest versions.

How to call a AVPlayer in XAMARIN iOS during notification instead of 30 second max duration notification sound?

I need to play a audio file which is 3 minutes length. But default notification sound does not play more than 30 seconds. So my idea is Calling a Avplayer
which will play my desired audio. But i do not know how to call this. Can any one please help me. I will be very grateful.
I am attaching my notification method here.
public void AVPlayer()
{
NSUrl songURL;
if (!MusicOn) return;
//Song url from your local Resource
songURL = new NSUrl("azan.wav");
NSError err;
player = new AVAudioPlayer(songURL, "Song", out err);
player.Volume = MusicVolume;
player.FinishedPlaying += delegate {
// backgroundMusic.Dispose();
player = null;
};
//Background Music play
player.Play();
}
public void CreateRequest(JamatTime jamat)
{
// Create action
var actionID = "pause";
var title = "PAUSE";
var action = UNNotificationAction.FromIdentifier(actionID, title, UNNotificationActionOptions.None);
// Create category
var categoryID = "message";
var actions = new UNNotificationAction[] { action };
var intentIDs = new string[] { };
var categoryOptions = new UNNotificationCategoryOptions[] { };
var category = UNNotificationCategory.FromIdentifier(categoryID, actions, intentIDs, UNNotificationCategoryOptions.None);
// Register category
var categories = new UNNotificationCategory[] { category };
UNUserNotificationCenter.Current.SetNotificationCategories(new NSSet<UNNotificationCategory>(categories));
// Rebuild notification
var content = new UNMutableNotificationContent();
content.Title = " Jamat Time alert";
content.Badge = 1;
content.CategoryIdentifier = "message";`enter code here`
content.Sound = UNNotificationSound.GetSound("sample.wav");
var times = new string[] { jamat.Asr, jamat.Dhuhr, jamat.Faijr, jamat.Ishaa, jamat.Jumah, jamat.Maghib };
int id = 0;
foreach (var time in times)
{
var ndate = DateTime.ParseExact(time, "h:mm tt", null);
var date = new NSDateComponents()
{
Calendar = NSCalendar.CurrentCalendar,
Hour = ndate.Hour,
Minute = ndate.Minute,
Second = 0
};
content.UserInfo = new NSDictionary<NSString, NSString>(
new NSString[] {
(NSString)"time1",
(NSString)"time2"
},
new NSString[] {
(NSString)DateTime.Now.ToString("h:mm tt"),
(NSString)time
});
var trigger = UNCalendarNotificationTrigger.CreateTrigger(date, true);
// ID of Notification to be updated
var request = UNNotificationRequest.FromIdentifier(id++.ToString(), content, trigger);
// Add to system to modify existing Notification
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err1) =>
{
if (err1 != null)
{
Console.WriteLine("Error: {0}", err1);
}
Console.WriteLine($"Success: {request}");
});
}
}
You can't play an audio file instead of the UNNotificationSound.
There's no way to trigger the player's play method when the local notification comes. You could only configure the sound property using the code you post above. And the file should be embedded in the bundle resource.
It seems you are aware of UNNotificationSound: https://developer.apple.com/documentation/usernotifications/unnotificationsound?language=objc. But I still want to remind you of the file's format and length limitations.
Finally I have solved my problem.
When a notification fires then WillPresentNotification() method hits and I simply call the AVplayer there and perfectly working. If u want to play sound via UNNotificationSound then not possible because that is limited by 30 second duration..but problem this works only in foreground.

Export payment in Applications Tab menu of Bill and Adjustments in Acumatica ERP system using webservices api

I need to export all records in Applications Tab Menu of Bill and Adjustments screen as I did in UI like this screenshot below.
I already create codes to provide it using this code below.
try
{
context.CookieContainer = new System.Net.CookieContainer();
context.Timeout = 10000000;
context.Url = url;
LoginResult login = context.Login(username, password);
AP301000Content konten = context.AP301000GetSchema();
//context.AP301000Clear();
konten.DocumentSummary.Type.Commit = false;
konten.DocumentSummary.Type.LinkedCommand = null;
var command = new Command[]
{
new Value { Value = "Bill", LinkedCommand = Konten.DocumentSummary.Type },
new Value { Value = "00123", LinkedCommand = konten.DocumentSummary.ReferenceNbr },
konten.DocumentSummary.Vendor,
konten.Applications.ReferenceNbrDisplayRefNbr,
konten.Applications.DocTypeDisplayDocType
};
var result = context.AP301000Export(command, null, 0, false, true);
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
finally
{
sCon.getLogout(context);
}
After i debug this code I got records only for VendorCD but Reference Nbr and Doc Type didn't exported. Please refer to this screenshot below.
please how to solve this issue.
Thanks
You should use "every" fields:
var command = new Command[]
{
konten.DocumentSummary.ServiceCommands.EveryDocType,
konten.DocumentSummary.ServiceCommands.EveryRefNbr,
konten.DocumentSummary.Vendor,
konten.Applications.ReferenceNbrDisplayRefNbr,
konten.Applications.DocTypeDisplayDocType
};

Keyboard quickly hides and reappears on Android using Xamarin Forms

We're trying to build a Chat App using Xamarin Forms, but we keep getting this annoying bug with the Android keyboard. Whenever the "Send" button is tapped, the focus on the Entry (text box for chatting) is lost and the keyboard disappears. That isn't what we wanted so we added this line to the TapGestureRecognizer:
messageEntry.Focus();
But for some reason, this doesn't happen fast enough, and often the keyboard goes down and immediately up again. This prevents users from quickly posting multiple message sequentially. Does anybody know how this can be fixed?
Thanks to the answer of #AdamKemp in this post, here is my solution. If the touch is within my EntryStackLayout (don't forget to create the empty custom renderer), then I don't dismiss the keyboard (which is what DispatchTouchEvent will do if CurrentFocus is EditText).
public class EditorAndButtonReproPage : ContentPage
{
public EditorAndButtonReproPage()
{
BackgroundColor = Color.Gray;
Padding = 50;
var editor = new Editor {HorizontalOptions = LayoutOptions.FillAndExpand};
var editorButton = new Button {Text = "OK", HorizontalOptions = LayoutOptions.End};
var editorLayout = new EntryStackLayout { Orientation = StackOrientation.Horizontal, Children = { editor, editorButton}, VerticalOptions = LayoutOptions.Start};
var entry = new ExtendedEntry { Placeholder = "Entry", HorizontalOptions = LayoutOptions.FillAndExpand };
var entryButton = new Button { Text = "OK", HorizontalOptions = LayoutOptions.End };
var entryLayout = new EntryStackLayout { Orientation = StackOrientation.Horizontal, Children = { entry, entryButton }, VerticalOptions = LayoutOptions.Start };
Content = new StackLayout {Children = {editorLayout, entryLayout}};
}
}
and in the MainActivity:
private bool _ignoreNewFocus;
public override bool DispatchTouchEvent(MotionEvent e)
{
var currentView = CurrentFocus;
var parent = currentView?.Parent?.Parent;
var entryStackLayout = parent as EntryStackLayout;
if (entryStackLayout != null)
{
var entryLayoutLocation = new int[2];
entryStackLayout.GetLocationOnScreen(entryLayoutLocation);
var x = e.RawX + entryStackLayout.Left - entryLayoutLocation[0];
var y = e.RawY + entryStackLayout.Top - entryLayoutLocation[1];
var entryStackLayoutRect = new Rectangle(entryStackLayout.Left, entryStackLayout.Top, entryStackLayout.Width, entryStackLayout.Height);
_ignoreNewFocus = entryStackLayoutRect.Contains(x, y);
}
var result = base.DispatchTouchEvent(e);
_ignoreNewFocus = false;
return result;
}
public override Android.Views.View CurrentFocus => _ignoreNewFocus ? null : base.CurrentFocus;
It'd be a bit of a hack, but you could spin off an async task that waits 50ms and then invokes the messageEntry.Focus() line on the main UI thread...

How to pin a contact tile to start from an application?

I have a hubtile in my application which opens contacts for dialling a number. Now, i wanted to pin that into the start page of windows and i am implementing this feature by using the below code:
private void Click_Tap(object sender, RoutedEventArgs e)
{
ShellTile oTile = ShellTile.ActiveTiles.FirstOrDefault(x =>
x.NavigationUri.ToString().Contains("flip".ToString()));
if (oTile != null && oTile.NavigationUri.ToString().Contains("flip"))
{
FlipTileData oFliptile = new FlipTileData();
oFliptile.Title = "Hello WP8!!";
oFliptile.Count = 11;
oFliptile.BackTitle = "Updated Flip Tile";
oFliptile.BackContent = "back of tile";
oFliptile.WideBackContent = "back of the wide tile";
oFliptile.SmallBackgroundImage = new Uri("Assets/Tiles/Flip/h.jpg", UriKind.Relative);
oFliptile.BackgroundImage = new Uri("Assets/Tiles/Flip/h.jpg", UriKind.Relative);
oFliptile.WideBackgroundImage = new Uri("Assets/Tiles/Flip/h.jpg", UriKind.Relative);
oFliptile.BackBackgroundImage = new Uri("/Assets/Tiles/Flip/h.jpg", UriKind.Relative);
oFliptile.WideBackBackgroundImage = new Uri("/Assets/Tiles/Flip/h.jpg", UriKind.Relative);
oTile.Update(oFliptile);
MessageBox.Show("Flip Tile Data successfully update.");
}
else
{
Uri tileUri = new Uri("/phoneNumberChooserTask.show()?tile=flip", UriKind.Relative);
ShellTileData tileData = this.CreateFlipTileData();
ShellTile.Create(tileUri, tileData, true);
}
}
private ShellTileData CreateFlipTileData()
return new FlipTileData()
{
Title = "",
BackTitle = "",
BackContent = "",
WideBackContent = "",
Count = 8,
SmallBackgroundImage = new Uri("/Assets/Tiles/Flip/h.jpg", UriKind.Relative),
BackgroundImage = new Uri("/Assets/Tiles/Flip/h.jpg", UriKind.Relative),
WideBackgroundImage = new Uri("/Assets/Tiles/Flip/h.jpg", UriKind.Relative),
};
}
The problem i am facing is when i run this on a device/emulator, Tile gets pin to start but when i click the tile on the start screen of my device/emulator debugger stops the process and the process breaks.
Can anyone guide me in the right direction ?
Tile can not launch anything except your app. Add into uri some code that will be parsed by your app and then your app should call phoneNumberChooserTask.show(). For example:
new Uri("/Chooser.xaml?tile=flip", UriKind.Relative);
Then, in the Chooser.xaml (page in your project), in the OnNavigatedTo detect the title value in the Uri and call phoneNumberChooserTask.show().

Categories

Resources