Unique ID for mobile device FMX - firemonkey

What is a good way to create a unique ID for mobile devices (iOS and Android) in a C++Builder FMX app?
In my case, I just want to let my app users vote, but only once per device (even if they delete the app and reinstall it). They stay anonymous, but just can't vote more than once.
I know Apple came out with DeviceCheck for Swift, but I don't know how to use it in C++.
iOS 11: The DeviceCheck API
DeviceCheck API - Unique Identifier for the iOS Devices

Update: This solution targets Android devices. I have no experience with iOS devices.
Original answer: It may be way too late but here's my solution using _di_JTelephonyManager
_di_JObject obj;
_di_JTelephonyManager tm;
UnicodeString id;
try {
obj = SharedActivityContext()->getSystemService(TJContext::JavaClass>TELEPHONY_SERVICE);
if (obj) {
tm = TJTelephonyManager::Wrap(static_cast<_di_ILocalObject>(obj)->GetObjectID());
if (tm) {
//only if SIM Card is in device:
//id = JStringToString(tm->getSubscriberId());
//will get IMEI or MEID number
id = JStringToString(TJSettings_Secure::JavaClass->getString
(SharedActivity()->getContentResolver(),
TJSettings_Secure::JavaClass->ANDROID_ID));
}
}
}
catch (Exception &e) {
//catch exceptions
}
Hope it is helpful :)

Related

Xamarin Essentials Android Contacts: is there a way to determine which phone number? EG: Home, Work, Mobile?

Xamarin Essentials Contacts: is there a way to determine which phone number is which? EG: Home, Work, Mobile?
This is just for Android only.
Currently it just has the phone number(s) only, but I have a need to only display Mobile phone numbers (for SMS) and I can't see a way to determine if a number is tagged as 'Mobile'. Like when you create a contact on your andriod phone, you can set the phone number to be Home, Mobile, Work, etc.
Or anyone know of another library that does this? thanks.
Let take the example from docs. You could use the property ContactType of type enum ContactType, but it only defines Unknown, Personal and Work values:
try
{
var contact = await Contacts.PickContactAsync();
if(contact == null)
return;
var phones = contact.Phones; // List of phone numbers
foreach (var phone in phones)
{
if (phone.ContactType == ContactType.Personal || phone.ContactType == ContactType.Work) //just an example
}
}
catch (Exception ex)
{
// Handle exception here.
}

Getting SSID of the connected wifi network in Xamarin.iOS, iOS 13

After passing from iOS 12 to 13 I am no more able to get the SSID of the connected wifi network.
I tried the solution for iOS 13 proposed in
this question
but with no result.
My previous successful code for iOS 12 (moreover 'CaptiveNetwork' is deprecated now):
if (CaptiveNetwork.TryGetSupportedInterfaces(out string[] supportedInterfaces) == StatusCode.OK)
{
foreach (var item in supportedInterfaces)
{
if (CaptiveNetwork.TryCopyCurrentNetworkInfo(item, out NSDictionary info) == StatusCode.OK)
{
var ssid = info[CaptiveNetwork.NetworkInfoKeySSID].ToString();
return ssid;
}
}
}
Any suggestion?
Updated for iOS 13: Apple announced that iOS 13, the CNCopyCurrentNetworkInfo API will no longer return valid Wi-Fi SSID and BSSID information.
If your app requires valid Wi-Fi SSID and BSSID information to function, you can do the following: · For accessory setup apps, use the NEHotSpotConfiguration API, which now has the option to pass a prefix of the SSID hotspot your app expects to connect to. · For other types of apps, use the CoreLocation API to request the user’s consent to access location information.
So, I updated the above solution in the following way:
Add this key to your info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your Description</string>
Use the CoreLocation API to request the user’s consent to access location information.
private void GetLocationConsent()
{
var manager = new CLLocationManager();
manager.AuthorizationChanged += (sender, args) => {
Console.WriteLine("Authorization changed to: {0}", args.Status);
};
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
manager.RequestWhenInUseAuthorization();
}
Call the GetLocationConsent() function before calling the "CaptiveNetwork".

Blocking specific USB drives on MacOS

I need to block specific USB drives on MacOS. I found two methods.
Use Disk Arbitration framework and register approval callback.(user mode)
Use MAC policy API in kernel extension and register mpo_mount_check_mount callback.(kernel mode)
In user mode, I can get a kDADiskDescriptionDeviceVendorKey which is the vender id of USB drive. I'm wondering how I can get the same information in mpo_mount_check_mount callback or some other API I don't know. The MAC policy API is undocumented and browsing the XNU source code is extremely challenging for a new MacOS developer.
This is a screenshot from IORegistryExplorer. Could I get this information from a kernel extension using MACF or other APIs? Thanks!
I can use DiskArbitration and IOKit frameworks to get vender id in user mode, but I cannot use the same code in kernel extension.
This is my code.
int GetVenderId(DADiskRef dsk, int *vid)
{
io_service_t ioService;
CFTypeRef vendorid;
ioService = DADiskCopyIOMedia(dsk);
if (0 != ioService)
{
vendorid = IORegistryEntrySearchCFProperty(ioService, kIOServicePlane, CFSTR("idVendor"), NULL, kIORegistryIterateParents | kIORegistryIterateRecursively);
if(0 != vendorid)
{
if (CFNumberGetValue(vendorid, kCFNumberIntType, vid))
{
return 0;
}
CFRelease(vendorid);
}
IOObjectRelease(ioService);
}
return 1;
}

Xamarin iOS Fails Calling DataServiceQuery

Just coming back to testing the iOS cross platform project of my solution today, I am receiving the error message "An error occured on client IDB4110776 while executing a reply for topic xvs/idb/4.11.0.776/stop-app" when trying to iterate the results of a DataServiceQuery, i.e.
foreach (IdentityEntitiesModel.Device device in response.EndExecute(result))
In general, looking at the response received, it looks basically ok, having the query path. It was working two months ago.
I am using Xcode 10.1 beta 2 (10O35n) against a iPhone with iOS 12.0 (16A366) from VS2017 15.8.5. Another developer just encountered the same error using Xcode 10 and IOS 10.14.1.
Where might I find details as to the "xvs/idb/4.11.0.776/stop-app" function?
It appears that iOS requires the call be marshalled to the main thread, i.e.
Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
{
try
{
foreach (IdentityEntitiesModel.Device device in response.EndExecute(result))
{
if (device.MAC == DeviceID)
{
activeDevice = device;
activeICID = device.ICID;
// Remark to debug new device
DeviceFound = true;
}
}
}
catch (DataServiceQueryException ex)
{
string error = ex.Message.ToString() + cr;
}
});
The solution should work across platforms.

Getting the SSID of the CONNECTED WIFI on IOS 12- Xamarin (Updated for iOS 13)

I could get the ssid of the connected wifi to my iPhone. After Installing Xcode 10 and Updating Visual Studio for Mac and Visual Studio 2017, it returns me an empty ssid.
This is my piece of code for getting the ssid:
public override string GetCurrentWiFi()
{
String ssid = "";
try
{
string[] supportedInterfaces;
StatusCode status;
if ((status = CaptiveNetwork.TryGetSupportedInterfaces(out supportedInterfaces)) != StatusCode.OK)
{
}
else
{
foreach (var item in supportedInterfaces)
{
NSDictionary info;
status = CaptiveNetwork.TryCopyCurrentNetworkInfo(item, out info);
if (status != StatusCode.OK)
{
continue;
}
ssid = info[CaptiveNetwork.NetworkInfoKeySSID].ToString();
}
}
}
catch
{
}
return ssid;
}
I tried to add "Access WiFi Information" entitlement for iOS 12 app as it is mentioned here but the app still get an empty ssid:https://forums.xamarin.com/discussion/139476/adding-access-wifi-information-entitlement-for-ios-12-apps
I would be thankful if anyone could help.
RESOLVED: I applied Access WIFI Information for my Apple ID. Then I regenerated my Provisioning profile again and open it in my Xcode. Do not forget to add Entitlements.plist in the Custom Entertainments in the ios Bundle Signing. Now it works correctly.
Updated for iOS 13: Apple announced that iOS 13, the CNCopyCurrentNetworkInfo API will no longer return valid Wi-Fi SSID and BSSID information.
If your app requires valid Wi-Fi SSID and BSSID information to function, you can do the following:
· For accessory setup apps, use the NEHotSpotConfiguration API, which now has the option to pass a prefix of the SSID hotspot your app expects to connect to.
· For other types of apps, use the CoreLocation API to request the user’s consent to access location information.
So, I updated the above solution in the following way:
Add this key to your info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your Description</string>
Use the CoreLocation API to request the user’s consent to access location information.
private void GetLocationConsent()
{
var manager = new CLLocationManager();
manager.AuthorizationChanged += (sender, args) => {
Console.WriteLine("Authorization changed to: {0}", args.Status);
};
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
manager.RequestWhenInUseAuthorization();
}
Call the GetLocationConsent() function before calling the "CaptiveNetwork".
To use this function in iOS 12 and later, enable the Access WiFi Information capability for your app .
So you have to check Access WiFi Infomation in appid.

Resources