Objective C fetch MobileOperator name via Simulator - ios

I have tried fetching carrier name by using the below code via iphone and ipad simulators with XCode7.3.1.But this return (null)
CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [networkInfo subscriberCellularProvider];
// Get carrier name
carrierName = [carrier carrierName];
Can anyone help me to find carrier name via simulator, without changing XCode system files

while we fetching the carrier value in the simulator it returns null only(because for carrier value we requires simcard),so we have to set the carrier value in the info.plist manually,i hope this answer will help you

In Apple Docs
if a user swaps the device’s SIM card with one from another provider,
while your application is running. This class also gives you access to
the CTCarrier object, which contains information about the user’s home
cellular service provider.
Since simulator doesn't have cellular service provider carrier will be nil.
You need device with sim card inserted to get any value.

No, In simulator it is not possible to get the carrierName. You need device with SIM card.

You will have to use a device to get this info. According to documentation:
If you configure a device for a carrier and then remove the SIM card,
this property retains the name of the carrier. The value for this
property is nil if the device was never configured for a carrier.
So nil in simulator is an expected return value.

Related

How to detect iOS SMS capability (NOT text messaging in general)

I'm writing an app that optionally allows you to send an SMS to a list of users. The app currently detects whether the device allows the sending of text messages using MFMessageComposeViewController.canSendText() and only displays the "Send SMS" button when the result is true.
Today, one of my users complained that when he hit the button on his Wifi-only iPad, nothing happened. As it turns out, canSendText() also returns true if the iOS device has the iMessage capability turned on, even if SMS is not supported. Turning the iMessage capability off in the iOS setting properly disables the "Send SMS" button.
The problem with sending the message via iMessage is that some recipients will have iMessage turned on and thus will receive the text message. But for the recipients without iMessage (it may be turned off or they may not be using an Apple device in the first place), those messages will not arrive. (When the MFMessageComposeViewController eventually comes up, those addresses are marked in red. But my average user is not going to understand that this means the message will not delivered.)
Does anybody know of a reliable method that tests for SMS capability specifically, not just for text messages (SMS, iMessage and MMS) in general?
As far as I know devices with iOS 5+ will return TRUE for MFMessageComposeViewController.canSendText() as they are capable of iMessage
So I assume you only need to send text if SIM card is installed on device.
But there is no way to detect if SIM card is installed on device. Still you can use workaround like :
#import<CoreTelephony/CTCallCenter.h>
#import<CoreTelephony/CTCall.h>
#import<CoreTelephony/CTCarrier.h>
#import<CoreTelephony/CTTelephonyNetworkInfo.h>
CTTelephonyNetworkInfo* info = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier* carrier = info.subscriberCellularProvider;
NSString *mobileCountryCode = carrier.mobileCountryCode;
NSString *carrierName = carrier.carrierName;
NSString *isoCountryCode = carrier.isoCountryCode;
NSString *mobileNetworkCode = carrier.mobileNetworkCode;
NSLog(#"\n %# \n %# \n %# \n %#", mobileCountryCode, carrierName, isoCountryCode, mobileNetworkCode);
Here, carrierName will return name when SIM card is present OR last use SIM card info. But others will be null if there is no SIM card installed.

Detect whether iPad supports sim card programmatically

Currently, I have an app that shows the 3G data / Wifi used by the user since the last reboot.
What I want to do is, if the app is running on an iPad which doesn’t support SIM card, I want to hide certain statistics shown to the user.
Is it somehow possible to detect whether the current iOS device supports a sim card or not?
As far as I know, you cannot detect if the SIM card is installed. You can only determine if a WWAN connection is available using Reachability or you can use CTCarrier
#import CoreTelephony;
-(BOOL)hasCellularCoverage
{
CTTelephonyNetworkInfo *networkInfo = [CTTelephonyNetworkInfo new];
CTCarrier *carrier = [networkInfo subscriberCellularProvider];
if (!carrier.isoCountryCode) {
NSLog(#"No sim present Or No cellular coverage or phone is on airplane mode.");
return NO;
}
return YES;
}

Get current type of internet connection

I want to get the technology of radio access (internet connection), so detect if the device is connected to Wifi or WWAN connection (and in this case, which type of WWAN : GPRS, EGDE, 3G, 3G+, 3G++, or 4G).
Does CTTelephonyNetworkInfo works for iPhone and iPad on iOS7.1 ?
I've tried to detect a Wifi connection on an iPad but I print a null result.
This is my code :
CTTelephonyNetworkInfo *telephonyInfo = [CTTelephonyNetworkInfo new];
NSLog(#"Current Radio Access Technology: %#", telephonyInfo.currentRadioAccessTechnology);
Someone can told me why ? I'm not sure to understand everything about this...
Thanks for your help
(Source : http://www.objc.io/issue-5/iOS7-hidden-gems-and-workarounds.html, section "Know your Radio")
That's because currentRadioAccessTechnology will return the radio access technology (not whether it's Wifi or WWAN). An example of return value is CTRadioAccessTechnologyLTE.
To get informed about whether your app is connect to Wifi or WWAN, you should use Reachability.
There are several implementations available.

Get MAC address of bluetooth low energy peripheral in iOS

I am currently working on an iOS application based on bluetooth low energy devices. In order to get a unique identifier to compare the peripherals got, I have to get the MAC address of the peripherals.
It is observed that the UUID property of a peripheral device varies across iOS devices and also for the peripheral device to get a UUID, it will have to get connected to a master device at least once. Since I have to deal with check-in's I don't want to establish a connection. As I went through the bluetooth services portal, I found that the device information itself is a service, which couldn't be retrieved unless a connection has been established between the master iOS device and the peripheral bluetooth low energy device.
I found that in Android we get the entire information of the device, including its MAC address (using getAddress()) when we get the response from the device on scanning itself.
I didn't find any properties in CBPeripheral class related to the device address.
Another way to get a unique parameter would be to customize the advertisement data to send additional information regarding the device, which requires more work on firmware side.
So is there any way in iOS that I could get the MAC address of the bluetooth low energy peripheral without establishing a connection?
Any help would be greatly appreciated.
CBPeripheral's identifier property will serve your purpose, available from a still-unconnected device in CBCentralManager's didDiscoverPeripheral delegate method:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
CBPeripheral *peripheral ...
NSUUID* serverId = [peripheral identifier];
I have a half dozen LE devices I'm experimenting with, including multiple sets of identical devices. I just confirmed that across two iOS devices, the identifiers for all of these LE widgets were different, but for EACH iOS device, the identifier for each widget was retained across application launches and even across app deletes and reinstalls. I would say this definitively proves that the OS is storing enough info internally that for a given iThing, you'll be able to distinguish between, and re-identify, all the peripherals your app encounters, without actually connecting to them.
Also note that the advertisementData, also available before connecting, is full of useful info like CBAdvertisementDataLocalNameKey, CBAdvertisementDataManufacturerDataKey, CBAdvertisementDataServiceUUIDsKey, CBAdvertisementDataSolicitedServiceUUIDsKey, and others, although none as certain to uniquely identify the device as [peripheral identifier] is.
I didn't try doing a device backup and restore to prove the UUIDs were retained, but I'd wager they are, and if they're not, it's something Apple would consider a bug.
Updated Answer :-
After iOS 12 we can get UDID
print(UIDevice.current.identifierForVendor)
print(UIDevice.current.identifierForVendor?.uuidString)
Before iOS 12**
There is no public API to get this information.
If this is an internal or jailbreak application you can get the value of the kLockdownBluetoothAddressKey key via liblockdown.dylib
Low energy peripherals may use privacy feature which hides the MAC address, so it is not necessarily even possible to get the address before connection or bonding. If you somehow get the MAC address which goes over the air, you need to handle privacy or you have interoperability problems.
Apple uses UUIDs to abstract these privacy features out so users do not need to worry about those.
Correct way to do that like you wrote is to either add some vendor specific data to advertisement packet or use the Device Information service.
On-behalf of the discussion of the other professionals I've found some facts which says -
“iOS hides the MAC address of the device and generates a UUID. The UUID on iOS is generated by the iOS device. Different iOS devices will get different UUIDs for the same peripheral. The MAC address is usually based on the hardware. If we both have iPhones and scan the same peripheral, we'll see different UUIDs. iOS generates the UUID on the device and hides the MAC address.

Summary - iOS doesn't let you get the MAC address of a device, it gives you a random UUID instead.“
Source - https://github.com/don/cordova-plugin-ble-central/issues/77
As per above study I've found that there’s not such a unique way to get connect to the board so far, Every board has a MAC address, which Doesn’t changes and easy to access in (only) Android, while iOS doesn’t allow to access MAC Address of the peripheral, however iOS use this MAC address to create a peripheral identifier (UUID), which is unique on (unique) device only. The peripheral identifier for a single Board is different for different iPhones devices (but unique on single device).
However we can connect to a board by searching with Peripheral's Bluetooth Service UUID, but this service UUID is same for all the boards of a kind say- “Adafruit Feather M0”. It means the App will look around the BLE boards of the same type (“Adafruit Feather M0”) and will get connect to ANY one of them. In order to connect to a particular user to a specific Board doesn’t seems to be possible so far due to the inaccessibility of MAC and giving the random UUID in iOS.
You can access to the MAC ADDRESS without problem in iOS 12.
To get the mac address you have to follow the next steps.
Parse the Data received by the BLE device to String.
extension Data{
func hexEncodedString() -> String {
let hexDigits = Array("0123456789abcdef".utf16)
var hexChars = [UTF16.CodeUnit]()
hexChars.reserveCapacity(count * 2)
for byte in self {
let (index1, index2) = Int(byte).quotientAndRemainder(dividingBy: 16)
hexChars.insert(hexDigits[index2], at: 0)
hexChars.insert(hexDigits[index1], at: 0)
}
return String(utf16CodeUnits: hexChars, count: hexChars.count)
}
}
Add a separator ":" to the address.
extension String {
func separate(every stride: Int = 4, with separator: Character = " ") -> String {
return String(enumerated().map { $0 > 0 && $0 % stride == 0 ? [separator, $1] : [$1]}.joined())
}
}
In didReadValueForCharacteristic( characteristic: CBCharacteritic) you can use the previous 2 functions to get the mac address.
func didReadValueForCharacteristic(_ characteristic: CBCharacteristic) {
if characteristic.uuid == BleDeviceProfile.MAC_ADDRESS, let mac_address = characteristic.value?.hexEncodedString().uppercased(){
let macAddress = mac_address.separate(every: 2, with: ":")
print("MAC_ADDRESS: \(macAddress)")
}
}
enjoy your mac address:
"MAC_ADDRESS: 00:0A:57:4E:86:F2"

Bluetooth peripheral has null UUID

I'm trying to connect a BTLE peripheral to my iOS app but the CBConcretePeripheral object that is sent to didDiscoverPeripheral has a null UUID.
This is the info from the CBConcretePeripheral Object retrieved on an iPhone 5.
<CBConcretePeripheral: 0x20043eb0 UUID = (null), Name = "Wahoo HRM V1.7", IsConnected = NO>
This works for some devices but not others.
This is the info from the CBConcretePeripheral Object retrieved on an iPhone 4s.
<CBConcretePeripheral: 0x1dde9720 UUID = <CFUUID 0x1dde9400> 5147BE71-E894-0152-5669-D640CA5E321C, Name = "Wahoo HRM V1.7", IsConnected = NO>
Apple have chopped and changed a bit with this, it depends on the version of iOS. I believe it relates to a privacy leak.
Some versions of iOS don't provide a UUID until after you connect to it, at which point you discover the same peripheral for a second time. The CBPeripheral object you are passed remains the same, so you can use that to determine if you are having your information updated about an existing peripheral or if it's a new peripheral. The documentation isn't great for CoreBluetooth, but there is additional information to be gained by reading the framework headers, and if I recall correctly, the iOS 7 documentation on CoreBluetooth is improved.

Resources