Windows Phone 10 Univrsal - get online contacts - contacts

I can get all the contacts from a windows phone 10 device.
I want to know if a contact is local contact or an online contact.
I used this code to indicate:
ContactStore contactstore = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AllContactsReadOnly);
ContactList = await contactstore.FindContactsAsync();
if (ContactList.Count > 0)
{
ienum = ContactList.GetEnumerator();
ienum.MoveNext();
IEnumerator<ContactConnectedServiceAccount> enum2 = ienum.Current.ConnectedServiceAccounts.GetEnumerator();
enum2.MoveNext();
string id = enum2.Current.ServiceName;
but it get to the catch exception scope..
I also tried to change the access type from AllContactsReadOnly to AppContactsReadWrite and it doesn't work and does the same.

Related

Notify User of New Signin with Firebase - Swift/Xcode

I have looked all over and can't figure out how to notify a user when a new device signs into their account. I'm using Firebase Authentication. I'd like to setup some kind of notification system or email that tells the user someone has signed into their account from a different device so they can know for security reasons.
Ideas?
Also, how could you monitor information about what device (s) are signed into a specific account? For example, maybe the user is curious how many devices he has signed into his account, what type of device they are, what the name of those devices are, and where they are located (example: San Antonio, Texas).
Ideas?
yes, you can use keychain for this situation. First you should create an uniqueId. After you can save to the db uniqueId. This value will change if the user uses another device. I'm using third party framework for Keychain services. You can use framework. It's perfect.
https://github.com/kishikawakatsumi/KeychainAccess
final class DeviceManager {
static let shared = DeviceManager()
private init() { }
var uniqueDeviceId: String {
get {
let keychain = Keychain(service: KeyManager.keychainServiceName).accessibility(.always)
if let deviceId = keychain[KeyManager.keychainDeviceIdKey] {
return deviceId
}
let vendorId = UIDevice.current.identifierForVendor!.uuidString
keychain[KeyManager.keychainDeviceIdKey] = vendorId
return vendorId
}
}
}
Super simple; have a field in your user document that stores a device name along with its status.
You app will be observing this users document and when something changes, all of the users devices will be notified of that change.
Let me set this up; here's a basic Firestore structure
users
uid_0
userName: "Jay"
devices:
device_0: offline
device_1: offline
When the app starts, it will add an observer to this users document (using the uid as the documentId)
func observeUser() {
let usersCollection = self.db.collection("users")
usersCollection.document("uid_0").addSnapshotListener { (documentSnapshot, err) in
guard let document = documentSnapshot else {
print("Error fetching document: \(err!)")
return
}
let device = document.get("devices") as! [String: String]
print(device)
}
}
Now in the Firestore closure shown above, if a users device changes status, offline to online for example, it outputs all of the devices to console. You would take whatever action is needed when the device changes status.
Keep in mind that if a NEW device is added, that event will also fire so you could present a message in the UI "A new device was added!"
So then some testing code that toggles the device_0 status from offline to online. I have a button click that does self.status = !self.status and then calls the toggleStatus function
var status = false
func toggleStatus() {
var isOnline = ""
if self.status == false {
isOnline = "online"
} else {
isOnline = "offline"
}
let userCollection = self.db.collection("users")
let thisDevice = "device_0"
let devicesDict = [
"devices":
[thisDevice: isOnline] //sets device_0 to offline or online
]
let document = usersCollection.document("uid_0").setData(devicesDict, merge: true)
}
In a nutshell, when a user authenticates with a device for the first time, it would perhaps ask for a device name, or craft one from the devices mac address or something under the hood. That device name is stored in the users document/devices with it's online status.
The device name would be stored locally as well, in user defaults for example so it's automatically sent up to Firestore upon login.
The end result here is that if any users devices change status; offline to online or vice versa, or any device is added or removed all of the devices are notified of that event.

Power BI REST API ExportToFileInGroup Not Working

I am able to programmatically log in to the PowerBI Client, gather my Workspaces as well as get a specific Report from a specific Workspace. I need to programmatically render that report to a .pdf or .xlsx file. Allegedly this is possible with the ExportToFileInGroup/ExportToFileInGroupAsync methods. I even created a very simple report without any parameters. I can embed this using the sample app from here. So that at least tells me that I have what I need setup in the backend. But it fails when I try to run the ExportToFileInGroupAsync method (errors below code.)
My Code is:
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new string[] {
PowerBiScopes.ReadReport,
PowerBiScopes.ReadDataset,
});
var userInfo = await graphServiceClient.Me.Request().GetAsync();
var userName = userInfo.Mail;
AuthDetails authDetails = new AuthDetails {
UserName = userName,
AccessToken = accessToken,
};
var credentials = new TokenCredentials($"{accessToken}", "Bearer");
PowerBIClient powerBIClient = new PowerBIClient(credentials);
var groups = await powerBIClient.Groups.GetGroupsAsync();
var theGroup = groups.Value
.Where(x => x.Name == "SWIFT Application Development")
.FirstOrDefault();
var groupReports = await powerBIClient.Reports.GetReportsAsync(theGroup.Id);
var theReport = groupReports.Value
.Where(x => x.Name == "No Param Test")
.FirstOrDefault();
var exportRequest = new ExportReportRequest {
Format = FileFormat.PDF,
};
string result = "";
try {
var response = await powerBIClient.Reports.ExportToFileInGroupAsync(theGroup.Id, theReport.Id, exportRequest);
result = response.ReportId.ToString();
} catch (Exception e) {
result = e.Message;
}
return result;
It gets to the line in the try block and then throws the following errors:
An error occurred while sending the request.
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
UPDATE
Relating to #AndreyNikolov question, here is our Embedded capacity:
After this was implemented, no change. Same exact error.
Turns out the issue was on our side, more specifically, security/firewall settings. Here is the exact quote from our networking guru.
"After some more investigation we determined that our firewall was causing this issue when it was terminating the SSL connection. We were able to add a bypass for the URL and it is now working as expected."

xamarin forms: Calling phone and sending email (IOS, Android and UWP)

Currently using following code for calling and email features, but it is only working in Android and not working in IOS. Also, I need these features in UWP.
For call:
string phoneno = "1234567890";
Device.OpenUri(new Uri("tel:" + phoneno));
For mail:
string email = "sreejithsree139#gmail.com";
Device.OpenUri(new Uri("mailto:" + email ));
Any package available for this?
Xamarin.Essentials (Nuget) is available as a preview package and contains functionality to both open the default mail app and attach information such as the recipients, subject and the body as well as open the phone dialer with a certain number.
There is also a blog post about Xamarin.Essentials available on blog.xamarin.com.
Edit:
As for your mail issue, Xamarin.Essentials expects an array of strings as recipients so you are able to send mail to multiple people at once. Just pass a string array with one single value.
var recipients = new string[1] {"me#watercod.es"};
If you're using the overload that expects an EmailMessage instance, you are supposed to pass a List of string objects.
In that case, the following should work:
var recipients = new List<string> {"me#watercod.es"};
Updating the complete code for calling and mailing features using Xamarin.Essentials, this might help others.
For call:
try
{
PhoneDialer.Open(number);
}
catch (ArgumentNullException anEx)
{
// Number was null or white space
}
catch (FeatureNotSupportedException ex)
{
// Phone Dialer is not supported on this device.
}
catch (Exception ex)
{
// Other error has occurred.
}
For Mail:
List<string> recipients = new List<string>();
string useremail = email.Text;
recipients.Add(useremail);
try
{
var message = new EmailMessage
{
//Subject = subject,
//Body = body,
To = recipients
//Cc = ccRecipients,
//Bcc = bccRecipients
};
await Email.ComposeAsync(message);
}
catch (Exception ex)
{
Debug.WriteLine("Exception:>>"+ex);
}
Hello to make a call in UWP:
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.ApplicationModel.Calls.PhoneCallManager"))
{
Windows.ApplicationModel.Calls.PhoneCallManager.ShowPhoneCallUI("123", "name to call");
}
To send a Text:
private async void ComposeSms(Windows.ApplicationModel.Contacts.Contact recipient,
string messageBody,
StorageFile attachmentFile,
string mimeType)
{
var chatMessage = new Windows.ApplicationModel.Chat.ChatMessage();
chatMessage.Body = messageBody;
if (attachmentFile != null)
{
var stream = Windows.Storage.Streams.RandomAccessStreamReference.CreateFromFile(attachmentFile);
var attachment = new Windows.ApplicationModel.Chat.ChatMessageAttachment(
mimeType,
stream);
chatMessage.Attachments.Add(attachment);
}
var phone = recipient.Phones.FirstOrDefault<Windows.ApplicationModel.Contacts.ContactPhone>();
if (phone != null)
{
chatMessage.Recipients.Add(phone.Number);
}
await Windows.ApplicationModel.Chat.ChatMessageManager.ShowComposeSmsMessageAsync(chatMessage);
}
as found in Microsoft documentation here: Compose SMS documentation
==> So you can make (If not already done) a shared service interface in your Xamarin app, then the implementation with these codes in your UWP app...
To send an email:
To send an email in UWP, you can refer to the Microsoft documentation too:
Send Email documentation (UWP)
Using a plugin
Else you can use a Xamarin plugin:
documentation: Xamarin cross messaging plugin
Nuget: Nuget plugin package
In our app, we are doing the phone calling with a DependencyService.
Therefore in our PCL, we have
public interface IPhoneCall
{
void Call(string number);
}
On the iOS side, the following method does the calling:
public void Call(string number)
{
if (string.IsNullOrEmpty(number))
return;
var url = new NSUrl("tel:" + number);
if (!UIApplication.SharedApplication.OpenUrl(url))
{
var av = new UIAlertView("Error",
"Your device does not support calls",
null,
Keys.Messages.BUTTON_OK,
null);
av.Show();
}
}
If don't want to wait for the Xamarin essentials that is still in pre-release as of today, you can use this open source plugin. It works on iOS, Android and UWP. There is a sample from the github documentation :
// Make Phone Call
var phoneDialer = CrossMessaging.Current.PhoneDialer;
if (phoneDialer.CanMakePhoneCall)
phoneDialer.MakePhoneCall("+27219333000");
// Send Sms
var smsMessenger = CrossMessaging.Current.SmsMessenger;
if (smsMessenger.CanSendSms)
smsMessenger.SendSms("+27213894839493", "Well hello there from Xam.Messaging.Plugin");
var emailMessenger = CrossMessaging.Current.EmailMessenger;
if (emailMessenger.CanSendEmail)
{
// Send simple e-mail to single receiver without attachments, bcc, cc etc.
emailMessenger.SendEmail("to.plugins#xamarin.com", "Xamarin Messaging Plugin", "Well hello there from Xam.Messaging.Plugin");
// Alternatively use EmailBuilder fluent interface to construct more complex e-mail with multiple recipients, bcc, attachments etc.
var email = new EmailMessageBuilder()
.To("to.plugins#xamarin.com")
.Cc("cc.plugins#xamarin.com")
.Bcc(new[] { "bcc1.plugins#xamarin.com", "bcc2.plugins#xamarin.com" })
.Subject("Xamarin Messaging Plugin")
.Body("Well hello there from Xam.Messaging.Plugin")
.Build();
emailMessenger.SendEmail(email);
}

ContactEndpoint phone, Lync 2013

my application that uses Lync 2013, communicates with a server via websocket, and receives notifications.
These notifications are in Json format, so I convert it to extract a string.
The string is a phone number, and I want to test if one of my contacts are the same phone number to display his name.
My If is always "false".
I wanted to use > and extract the value of DisplayName (phone number as string) but i didn't know how to do it.
This is my code.
foreach (var group in client.ContactManager.Groups)
{
foreach (Contact contact in group)
{
List<object> endpoints = (List<object>)contact.GetContactInformation(ContactInformationType.ContactEndpoints);
List<object> phoneNumbers = endpoints.Cast<object>().Where<object>(N => ((ContactEndpoint)N).Type == ContactEndpointType.HomePhone ||
((ContactEndpoint)N).Type == ContactEndpointType.MobilePhone ||
((ContactEndpoint)N).Type == ContactEndpointType.WorkPhone ||
((ContactEndpoint)N).Type == ContactEndpointType.OtherPhone).ToList();
if (phoneNumbers.ToList().Contains(call.caller))
{
MessageBox.Show(contact.GetContactInformation(ContactInformationType.DisplayName).ToString());
}
}
}
You can ask the contact manager for a contact directly by the number formatted as a tel URL. e.g. "el:12345678"
e.g.
var contact = client.ContactManager.GetContactByUri("tel:" + call.caller);

Custom contact has invalid ContactListId on Windows Universal

I am experiencing some strange behaviour in the Windows Universal Contacts API. Consider the following method:
public async Task TestContactStore()
{
//Fetch store and create custom contact list
ContactStore localStore = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
var list = await localStore.CreateContactListAsync("Contact Store Test");
//Create new contact in custom contact list
await list.SaveContactAsync(new Contact() { Name = "Test", LastName = "Contact"});
ContactStore allAccessStore = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AllContactsReadOnly);
//Print all available contact lists
Debug.WriteLine("All Contact Lists");
var contactLists = await allAccessStore.FindContactListsAsync();
foreach (var contactList in contactLists)
{
Debug.WriteLine(contactList.DisplayName + ": " + contactList.Id);
}
//Print all available contacts
Debug.WriteLine("All Contacts");
var contacts = await allAccessStore.FindContactsAsync();
foreach (var contact in contacts)
{
Debug.WriteLine(contact.Name + " " + contact.LastName + ": " + contact.ContactListId);
}
}
It creates a contact list for my app ("Contact Store Test"). Then it saves a new Contact to this list ("Test Contact"). After this it prints all available contact lists and then all contacts.
The output is:
All Contact Lists
Hotmail: 24,5,5
Contact Store Test: 24,11,11
All Contacts
Hotmail Contact: 24,5,5
Test Contact: 24,5,5
Why does the Test Contact show up with the same ContactListId as the Hotmail-list? In the contacts app on the phone it shows up as belonging to the Contact Store Test-list. What am I missing?
I have now done some further research regarding this behavior. In the latest build 10.0.10512.1000, this behavior has changed. All ContactListId return empty string now.
When fetching contacts the way I did in my example above
var contactLists = await allAccessStore.FindContactListsAsync();
foreach (var contact in contactLists)
{
Debug.WriteLine(contactList.DisplayName + ": " + contactList.Id);
}
It seems as though the contacts in the list are always aggregated contacts (even if they are not linked in the address book). Aggregated contacts (apparently) always has empty ContactListId and AggregateId. The Id-property always matches the AggregateId-property of the corresponding raw contacts.
To get the corresponding contact list id, the raw contacts for that aggregate needs to be fetched:
var contactLists = await allAccessStore.FindContactListsAsync();
foreach (var contact in contactLists)
{
var rawContacts = await allAccessStore.AggregateContactManager.FindRawContactsAsync(aggregateContact);
foreach (var raw in rawContacts)
{
Debug.WriteLine(contactList.DisplayName + ": " + contactList.Id);
}
}
This gives expected ContactListId.