How to convert a NSString to a String in MonoTouch - xamarin.ios

I am trying to implement push notifications for MonoTouch but I couldnĀ“t find samples of this anywhere. My problem is trying to read the deviceID into a .NET string.
The output below is just a lot of question marks so I am doing something wrong here.
Any help would be greatly appreciated!
public override void RegisteredForRemoteNotifications (UIApplication application, NSData deviceToken)
{
Console.WriteLine("Converting device ID...");
NSString s = NSString.FromData(deviceToken, NSStringEncoding.UTF8);
Console.WriteLine("DEVICE ID IS: " + s);
s = NSString.FromData(deviceToken, NSStringEncoding.ASCIIStringEncoding);
Console.WriteLine("DEVICE ID IS: " + s);
s = NSString.FromData(deviceToken, NSStringEncoding.Unicode);
Console.WriteLine("DEVICE ID IS: " + s);
}

There is an operator for implicit conversion in MonoTouch.
So you just do:
NSString s = NSString.FromData(deviceToken, NSStringEncoding.UTF8);
string csstring = s;
// done
Alternatively, you can use NSString's ToString() method:
NSString s = NSString.FromData(deviceToken, NSStringEncoding.UTF8);
string csstring = s.ToString();
Here's related documentation.

Here's a great article showing how to do push notifications with MonoTouch:
http://weblogs.thinktecture.com/cweyer/2010/12/implementing-push-notifications-for-ios-with-c-monotouch-using-the-cloud-urban-airship.html
Here's the snippet that does what you want:
var str = (NSString)Runtime.GetNSObject (
Messaging.intptr_objc_msgSend (deviceToken.Handle, new Selector("description").Handle));
var deviceTokenString = str.ToString ().Replace ("<", "").Replace (">", "").Replace (" ", "");

I've managed to implement this, and I used the following code:
NSString newDeviceToken = new NSString(MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr(new MonoTouch.ObjCRuntime.Class("NSString").Handle, new MonoTouch.ObjCRuntime.Selector("stringWithFormat:").Handle, strFormat.Handle, deviceToken.Handle));
string token = newDeviceToken.ToString();
This will provide you with a string which reads
< 64characterlonghexstring >
You can use a Regex to get rid of the spaces and the "<" ">" character as required.
I found the following project very useful in getting a Monotouch implementation of push notifications working:
C# Apple Push Notification Service - it provides client side code as well as server side code.

Related

Get IOBluetoothDevice * from CBPeripheral * (Mac OS X)

I am wondering if there is a way i can get an IOBluetoothDevice * object from a CBPeripheral * object because I am making an advanced bluetooth controller framework (Its going to be based on IOBluetooth) and Im using it so scan for Bluetooth Classic and Bluetooth Low Energy devices. Here are some of the problems:
IOBluetooth does allow you to search for both networks but for some reason its not showing up all of the Bluetooth Low Energy Devices that CoreBluetooth is.
If I use CoreBluetooth to search for Bluetooth Low Energy Devices I won't be able to get the address which I require for later use.
So is there any way i can get an IOBluetoothDevice object from a CBPeripheral?
thanks :D
I found out that I can search through /Library/Preferences/com.apple.bluetooth.plist > CoreBluetoothCache which just happens to contain the UUID and in its dictionary DeviceAddress = the address ;).
so I can get the UUID of a CBPeripheral by using the method
NSString *uuid = [[<*CBPeripheral*> identifier] UUIDString];
and then looking it up in the property list
NSDicionary *btdict = [NSDictionary dictionaryWithContentsOfFile:#"/Library/Preferences/com.apple.bluetooth.plist"];
NSDictionary *bleDevices = [btDict objectForKey:#"CoreBluetoothCache"];
NSString *address = [[bleDevices objectForKey:uuid] objectForKey:#"DeviceAddress"];
Then create a new IOBluetoothDevice with that address:
IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:address];
Its as easy as that :D
Swift 5.3 solution:
fileprivate func getDeviceAddress(for cbPeripheral: CBPeripheral) -> String?
{
if let userDefaults = UserDefaults(suiteName: "/Library/Preferences/com.apple.Bluetooth")
{
if let coreBluetoothCache = userDefaults.object(forKey: "CoreBluetoothCache") as? [String : Any]
{
if let deviceData = coreBluetoothCache[cbPeripheral.identifier.uuidString] as? [String : Any]
{
return deviceData["DeviceAddress"] as? String
}
}
}
return nil
}
Usage:
if let deviceAddress = self.getDeviceAddress(for: peripheral)
{
if let bluetoothDevice = IOBluetoothDevice(addressString: deviceAddress)
{
// Do your stuff
}
}

Can't seem to get my string stripper to work correctly in c++

Question I have is I am trying to strip out all "%" of a string called "workorder" and for some reason it's not working any help would be very much appreciated!
example:
String ^ workorder = "%QW1234%12%3"
with the below code I want it to spit out the workorder string like so = "QW1234123"
HERE IS MY CODE
private: System::Void workorder_text_TextChanged(System::Object^ sender, System::EventArgs^ e) {
String ^ workorder;
workorder = workorder_text->Text;
//I CANT USE WORKORDER STRING FOR wO string for some reason....
string wO(workorder);
char bad_chars_wo[] = "%";
for (unsigned int i = 0; i < strlen(bad_chars_wo); ++i)
{
wO.erase (std::remove(wO.begin(), wO.end(), bad_chars_wo[i]), wO.end());
}
}
Do you have a real need to mix System::String and std::string objects here (as in, mix CLI strings and C++ strings)?
The simplest solution to your problem is to use the methods provided by System::String:
auto workorder = workorder_text->Text;
workorder = workorder->Replace("%", String::Empty);
If you really need a std::string for later processing, you can marshal the System::String:
#include <msclr/marshal_cppstd.h>
auto wO = msclr::interop::marshal_as<std::string>(workorder);
See the docs here.

Windows 10 get DeviceFamilyVersion

I'm working windows 10 10240 Univasal windows app, when i use Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamilyVersion to get deivce version, it return a string "2814750438211605" instead of a version format (major.minor.revision.build).
Anyone can tell me what the string "2814750438211605" means?
The Windows 10 OS version value is located in this string property:
Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamilyVersion
It returns string value like "2814750438211613".
To convert this long number to readable format use this:
string sv = AnalyticsInfo.VersionInfo.DeviceFamilyVersion;
ulong v = ulong.Parse(sv);
ulong v1 = (v & 0xFFFF000000000000L) >> 48;
ulong v2 = (v & 0x0000FFFF00000000L) >> 32;
ulong v3 = (v & 0x00000000FFFF0000L) >> 16;
ulong v4 = v & 0x000000000000FFFFL;
string version = $"{v1}.{v2}.{v3}.{v4}"; // == 10.0.10240.16413
Your application should treat the as opaque data and just log it "as is". It's a 64-bit decimal value as a string.
Remember the intent of this API is to provide a log string from which you can reconstruct the OS version number for support/analytics. On your server-side analysis, you'd convert it if needed or just use it as a unique version identifier... If you are actually trying to parse it runtime, then you are using it incorrectly and quite likely to recreate same problems that resulted in GetVersionEx and VerifyVersionInfo being deprecated in the first place.
Do not parse the string at runtime in your app. Just store "as is" Remember that with Windows 10, a customer really has no idea what you mean if you ask "What version of Windows do you have?". The answer is "10" and will likely still be "10" for a long time to come.
If you found this question and like me you are looking for a way to do this in JavaScript, then you might find this useful.
getDeviceFamilyVersion() {
let deviceFamilyVersion = Windows.System.Profile.AnalyticsInfo.versionInfo.deviceFamilyVersion;
let deviceFamilyVersionDecimalFormat = parseInt(deviceFamilyVersion);
if (isNaN(deviceFamilyVersionDecimalFormat)) {
throw new Error('cannot parse device family version number');
}
let hexString = deviceFamilyVersionDecimalFormat.toString(16).toUpperCase();
while (hexString.length !== 16) { // this is needed because JavaScript trims the leading zeros when converting to hex string
hexString = '0' + hexString;
}
let hexStringIterator = 0;
let versionString = '';
while (hexStringIterator < hexString.length) {
let subHexString = hexString.substring(hexStringIterator, hexStringIterator + 4);
let decimalValue = parseInt(subHexString, 16);
versionString += decimalValue + '.';
hexStringIterator += 4;
}
return versionString.substring(0, versionString.length - 1);
}
Just a nifty way of doing this .. I Creadted a Enum that is used to match predefined device families
public enum DeviceFamily
{
Unknown,
Desktop,
Tablet,
Mobile,
SurfaceHub,
Xbox,
Iot
}
This method will check and parse it into the enum.
var q = ResourceContext.GetForCurrentView().QualifierValues;
if (q.ContainsKey("DeviceFamily"))
{
try
{
Enum.Parse(typeof(DeviceFamily) , q["DeviceFamily"]);
//send the user notification about the device family he is in.
}
catch (Exception ex) { }
}

How to use ABPeoplePickerNavigationController in MonoTouch to pick a specific email address or phone number of a contact?

I have been using the ABPeoplePickerNavigationController in a project, written in MonoTouch, to pick a specific email address or phone number of a contact.
The code set a delegate, and in the delegate I implemented the ShouldContinue method, and retrieved the contact using the Handle property of all contacts. Unfortunately, it looks like something changed, or that I used undocumented features, or that I was simply lucky, because now when I'm in the process of updating the app for iPhone 5, the code no longer works.
Edit: Ok, my initial thoughts was that this was caused by changes in MonoTouch, since there has been quite a few updates since I last worked on this app. However, I now removed it from my device and downloaded the version I have on the app store, and it crashes in the same manner, null reference exception.
This means it is an iOS upgrade that made my code non-functional.
The goal of my code:
Pick a person's specific email address, not just the person, but navigating into the details of the person, and selecting a specific email address or telephone number.
The below code deals with phone numbers only, the email code looks 95% similar.
Here is the code that constructs the picker:
var picker = new ABPeoplePickerNavigationController();
picker.Init();
picker.DisplayedProperties.Clear();
picker.DisplayedProperties.Add(ABPersonProperty.FirstName);
picker.DisplayedProperties.Add(ABPersonProperty.Phone);
var del = new PhonePickerDelegate();
picker.Delegate = del;
Here is the delegate class:
private class PhonePickerDelegate : ABPeoplePickerNavigationControllerDelegate
{
public override bool ShouldContinue(ABPeoplePickerNavigationController peoplePicker, IntPtr selectedPerson, int propertyId, int identifier)
{
peoplePicker.DismissModalViewControllerAnimated(true);
// THE NEXT LINE IS THE ONE THAT NO LONGER WORKS
var contact = peoplePicker.AddressBook.SingleOrDefault(s => s.Handle == selectedPerson) as ABPerson;
using (var phones = contact.GetPhones())
{
int index = phones.GetIndexForIdentifier(identifier);
var phone = phones.GetValues()[index];
var name = (contact.FirstName + " " + contact.MiddleName).Trim() + " " + contact.LastName;
Selected(name + ": " + phone);
}
return false;
}
public override void Cancelled(ABPeoplePickerNavigationController peoplePicker)
{
peoplePicker.DismissModalViewControllerAnimated(true);
}
}
Unfortunately this code no longer finds the correct contact, as none of the contacts has a Handle value that corresponds to the selectedPerson IntPtr value.
My questions are these:
How can I fix the above code?
Can I fix the above code?
Is there some other class/method/delegate/event or whatnot I should be using instead?
You could do something like the following:
Note that AppDelegate.navigation would be your current NavigationController
using MonoTouch.AddressBookUI;
using MonoTouch.AddressBook;
ABPeoplePickerNavigationController _contactController = new ABPeoplePickerNavigationController ();
AppDelegate.navigation.PresentViewController (_contactController, true, null);
_contactController.Cancelled += delegate {
AppDelegate.navigation.DismissViewController (true, null);
return;
};
_contactController.SelectPerson += delegate(object sender, ABPeoplePickerSelectPersonEventArgs e) {
_importedContact = e.Person;
AppDelegate.navigation.DismissViewController (true, delegate {
// What to do when you dismiss the picker here.
});
};
e.Person is only going to give you the whole contact. You would want to do something like:
e.Person.GetEmails().FirstOrDefault
Hope this helps

how to convert object into string?

I have this problem converting object into string... I make use of the toString() function... and since the conversion of object into string were inside the try{}catch(exception e){}, i keep on receiving an output error: For input string: ""
What should be the problem if i keep on receiving an error message like that?
More elaboration:
the Object came from a jComboBox
which consists of items from a
database.
I am using a JFrame Form instead of
a Java Class.
All i want to do is to capture the selected Item from the JComboBox which happens to be an object. And then after capturing it. I'll use the value for my query in the database.
Here's my code(partial):
private void SUBMITActionPerformed(java.awt.event.ActionEvent evt) {
try {
Class.forName(Connect.DRIVER);
Connection con = DriverManager.getConnection(Connect.CONNECTION_STRING,
Connect.USERNAME, Connect.PASSWORD);
Object obj = jComboBox1.getSelectedItem();
String item_name = obj.toString();
int month = jMonthChooser.getMonth();
int q_box = Integer.parseInt(quantity_box_txtbox.getText());
double unit_price_box = 0;
int q_pc = Integer.parseInt(quantity_pc_txtbox.getText());
double unit_price_pc = 0;
double sub_total_box = 0;
double sub_total_pc = 0;
double grand_total = 0;
//Testing
System.out.println(jMonthChooser.getMonth());
System.out.println(item_name);
} catch (Exception e) {
System.out.println("Error: "+e.getMessage());
}
}
If you have anything you don't understand regarding with the way I explain my question please tell me... i'll try my best to elaborate further.
Thanks in advance.
:)
here's the complete error:
Error: java.lang.NumberFormatException : For input string: ""
Well, to start with:
Don't catch just Exception; catch specific subclasses
Don't just catch the exception; you almost certainly want to propagate it up to the caller
Don't log just the message - log the whole exception, including the stack trace and exception type.
The exception looks like it's trying to parse a string - not trying to convert an object to a string. I strongly suspect that the problem is one of these lines:
int q_box = Integer.parseInt(quantity_box_txtbox.getText());
int q_pc = Integer.parseInt(quantity_pc_txtbox.getText());
My guess is that one of the textboxes is empty - so you're effectively calling Integer.parseInt("") which is failing.

Resources