Push notification not register to the app on iOS 13 - ios

I build my app and I put a breakpoint in didRegisterForRemoteNotificationsWithDeviceToken but it's not triggered.
It works fine on other versions of iOS.
Is this a bug in iOS 13 or did I miss something new in iOS 13?
I use Xcode Beta 6 and iOS 13 beta 8.

The aforesaid problem could also be resolved by reconnecting wifi or switching between wifi and cellular data.
Moreover, following changes in iOS 13 affected push notification implementation.
Prior to iOS 13 many of us used to do
(deviceToken as NSData).description
// Used to return as follows
"<965b251c 6cb1926d e3cb366f dfb16ddd e6b9086a 8a3cac9e 5f857679 376eab7C>"
let tokenData = deviceToken as NSData
let token = tokenData.description
let token = "\(deviceToken)".replacingOccurrences(of: " ", with: "")
.replacingOccurrences(of: "<", with: "")
.replacingOccurrences(of: ">", with: "")
In iOS 13 apple has changed the implementation of its description method for NSData class.
So, it returns
"{length = 32, bytes = 0x965b251c 6cb1926d e3cb366f dfb16ddd ... 5f857679 376eab7c }" // in iOS 13.
Which ended up breaking push notifications implementation for many applications.
From now on, if you need to convert your push notification registration deviceToken into a Base16-encoded / hexadecimal string representation, you should do the following for Swift language
let deviceTokenString = deviceToken.map { String(format: "%02x", $0)
}.joined()
For Objective C, use following code
- (NSString *)hexadecimalStringFromData:(NSData *)deviceToken {
NSUInteger dataLength = deviceToken.length;
if (dataLength == 0) {
return nil;
}
const unsigned char *dataBuffer = (const unsigned char *)deviceToken.bytes;
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (NSInteger index = 0; index < dataLength; ++index) {
[hexString appendFormat:#"%02x", dataBuffer[index]];
}
return [hexString copy];
}
I came across a comprehensive article on the given topic
https://nshipster.com/apns-device-tokens/

As what I understood from trying a lot things about this issue is : sometimes iOS forcing the kind of connection to register device token to apple server.
If you are on WI-FI and didRegisterForRemoteNotificationsWithDeviceToken not called even though you are sure your implemantation of remote notification flow, try switching 3G or 4G. If it is not possible (a test device with no sim) try going to flight mode and activate wireless (which solved our problem).
If you are on 3G - 4G, try switching to wireless connection (There may be a problem if you are using vpn, proxy etc. disable all of them first).
If not other Stackoverflow users suggested deleting the app then restarting the device.

If the didRegisterForRemoteNotificationsWithDeviceToken is not triggering at all, try this.
I tried a lot to fix this issue with my wifi network, but it didnt fixed. So I changed my network to the cellular data and the didRegisterForRemoteNotificationsWithDeviceToken started triggering again
Also, if you used your internet connection in the MAC to share using USB. Turn it off & connect your IPhone with a normal wifi or mobile data.

if u use the testing device (without sim), try to put the sim card and install the app and gave the , it's worked for me.

Related

Flutter : IOS to IOS Broadcast Beacon not working

I'm currently building an app that turns my device into a Beacon while simultaneously scanning for other Beacons.
So I can keep track of beacons that I had come in contact with.
Problem
Current I've tested this code in the following Scenarios:
Android TO Android - Broadcasting & Scanning - Working well
Android To IOS - BroadCasting & Scanning Both ways - Working well
IOS to IOS - Not Working (When I broadcast UUID from IOS Device, I can see UUID in Android device but I can't see UUID in any IOS device.)
I installed this piece of code in 4 devices (2 Android & 2 IOS). Now all 4 devices are broadcasting different UUID's and at the same time listening.
In Android Devices, I see 1 UUID of another Android Device and 2 UUID's of IOS Devices
In IOS Devices, I see 2 Android UUID's but I cannot see another IOS Device UUID.
This is very strange, and I need help to solve this, please!
I've currently implemented 2 packages to achieve this functionality :
(1) For broadcast
beacon_broadcast: https://pub.dev/packages/beacon_broadcast
version : 0.2.1
(2) For scan other beacons
flutter_blue: https://pub.dev/packages/flutter_blue
version : 0.6.3+1
These are some glimpse of my code
(1) For Broadcasting
String UUID = 'DYNAMIC_UUID_FOR_EACH_DEVICE';
static const MAJOR_ID = 1;
static const MINOR_ID = 30;
static const TRANSMISSION_POWER = -59;
static const IDENTIFIER = 'com.example.myDeviceRegion';
static const LAYOUT = 'm:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24';
static const MANUFACTURER_ID = 0x004c;
BeaconBroadcast beaconBroadcast = BeaconBroadcast();
beaconBroadcast
.setUUID(UUID)
.setMajorId(MAJOR_ID)
.setMinorId(MINOR_ID)
.setTransmissionPower(TRANSMISSION_POWER)
.setIdentifier(IDENTIFIER)
.setLayout(LAYOUT)
.setManufacturerId(MANUFACTURER_ID);
.start();
(2) For Scanning
FlutterBlue flutterBlue = FlutterBlue.instance;
flutterBlue.startScan(timeout: Duration(seconds: 30));
flutterBlue.scanResults.listen((List<ScanResult> results) {
print('scanningListen...');
for (ScanResult result in results) {
result.advertisementData.manufacturerData.forEach((item, hexcodeAsArray) => {
print("calculated UUID String : " + calculateHexFromArray(v));
_addToScanResult(calculateHexFromArray(v));
});
}
}
String calculateHexFromArray(decimalArray) {
String uuid = '';
decimalArray.forEach((i) => {uuid += i.toRadixString(16).padLeft(2, '0')});
String uuid1 = uuid.substring(4, uuid.length - 12);
return uuid1.toUpperCase();
}
Unfortunately, you cannot use FlutterBlue to detect iBeacon packets on iOS.
Why? FlutterBlue uses raw bluetooth scanning to detect beacons, which under the hood means using the native CoreBluetooth scanning APIs on iOS. Apple blocks CoreBluetooth APIs from reading the raw bytes of any bluetooth advertisement decodable as an iBeacon advertisement. While this may sound crazy, it is likely motivated by misguided security concerns by Apple. Read more in my blog post here: CoreBluetooth Doesn't Let You See iBeacons
Two options to fix this:
Switch to using the AltBeacon format. Simply change LAYOUT = 'm:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25'; and MANUFACTURER_ID = 0x0118;
This will work, but has the disadvantage of the advertisement only being detectable on iOS in the foreground.
Switch to using a different detection library on iOS that uses CoreLocation (the only API allowed to detect iBeacon on iOS) instead of CoreBluetooth. That means giving up FlutterBlue in favor of FlutterBeacon or similar.

Which unique device identifier do we have on iOS that does not change when an application is installed / removed / re-installed

I want to be collecting both the installation event (on the new app) and the account creation event (on all the old apps).
To ensure uniqueness and prevent fraud (that is each installation should correspond to a unique device, and should remain the same event if the app is un-installed and re-installed again on the same device) we can use hardware identifiers that can survive uninstall.
On android phone IMEI can be used as unique identifier, but this solution is not repeatable on iOS as Apple does not give access to any hardware or unique identifier for privacy reason.
I tried the approaches proposed in the following links:
link1
link2
link3
From link 1 & 3 I tried:
let deviceID = UIDevice.current.identifierForVendor!.uuidString
But this does not provide a unique ID that will remain the same once the app is un-installed and re-installed again.
Please is there a better approach for me to handle this issue in swift. Thank you!
You can use Device Check API introduced in iOS 11, if you want to identify user's device even if user reinstalls your app.
Your server can use the generated token on the apple device. for more details please refer the following documentation
https://developer.apple.com/documentation/devicecheck/dcdevice/2902276-generatetoken
After UUID deprication there is no way 100% accomplish that , you can store an identifier in keychain but starting from iOS 10.3 , when you delete the app , all associated keychain items will be deleted
Currently there is no way(Before iOS 5 it was) to get static UDID or any device related ID. I also gone through this problem and I did followings to achieve.
Create own random number
- (NSMutableString*)getSecureGeneratedNumber
{
uint8_t randomBytes[16];
int randomNumber = SecRandomCopyBytes(kSecRandomDefault, 16, randomBytes);
NSMutableString *uuidStringReplacement;
if(randomNumber == 0) {
uuidStringReplacement = [[NSMutableString alloc] initWithCapacity:16*2];
for(NSInteger index = 0; index < 16; index++)
{
[uuidStringReplacement appendFormat: #"%02x", randomBytes[index]];
}
NSLog(#"uuidStringReplacement is %#", uuidStringReplacement);
} else {
return 0;
NSLog(#"SecRandomCopyBytes failed for some reason");
}
return uuidStringReplacement;
}
Save this random number in User Default or Keychain
[[NSUserDefaults standardUserDefaults] setObject:randomNumber forKey:#"randomNum"];
[[NSUserDefaults standardUserDefaults]synchronize];

Is it possible to get wifi signal strength in ios 9

I want to check WIFI signal strength to display some kind of message for weak WIFI signal.
I fount that it is not possible in iOS 8 and older.
Is it possible to get wifi signal strength in iOS 9? and if answer is yes then How?
Yes , it is possible in iOS 9.Look into NEHotspotNetwork
Register your app as Hotspot helper. (forums.developer.apple.com/message/30657#30657)
#import <NetworkExtension/NetworkExtension.h>
for(NEHotspotNetwork *hotspotNetwork in [NEHotspotHelper supportedNetworkInterfaces]) {
NSString *ssid = hotspotNetwork.SSID;
NSString *bssid = hotspotNetwork.BSSID;
BOOL secure = hotspotNetwork.secure;
BOOL autoJoined = hotspotNetwork.autoJoined;
double signalStrength = hotspotNetwork.signalStrength;
}
It is, but you need permission from Apple. Once Apple allows you to use the HotspotHelper framework, you'll be able to create profiles with the hotspot helper entitlements. Check this post: How to get Wifi SSID in iOS9 after CaptiveNetwork is deprecated and calls for Wifi name are already blocked

iOS MDM: Can we get to know whether device is rooted or jailbroken?

I am working on MDM implementation for iOS. I want to know whether there any command using which we can get to know whether iOS device is rooted or jailbroken?
I had seen the MDM protocol reference and I haven't found any field in DeviceInformation command to know this.
How server can know this status from device?
The Apple MDM protocol does not have a way to check if a device is jailbroken. MDM vendors will usually come up with their own solution for this.
You can look for Cydia (or similar apps) with NSFileManager. And you should check if you have access to the bash on the phone. You can try something like this:
- (BOOL) isJailbroken
{
//If the app is running on the simulator
#if TARGET_IPHONE_SIMULATOR
return NO;
//If its running on an actual device
#else
BOOL isJailbroken = NO;
//This line checks for the existence of Cydia
BOOL cydiaInstalled = [[NSFileManager defaultManager] fileExistsAtPath:#"/Applications/Cydia.app"];
FILE *f = fopen("/bin/bash", "r");
if (!(errno == ENOENT) || cydiaInstalled) {
//Device is jailbroken
isJailbroken = YES;
}
fclose(f);
return isJailbroken;
#endif
}
This code is not really tested.. let me know if it worked.

Transfer data between iPhone and Google Glass

I am looking to connect my phone to my Google Glass and transfer data (photos, text, etc.) between the two.
I was thinking of using Bluetooth LTE but as I understand it, Glass does not support it because it is only running version 4.0.3 (or similar) of Android.
I know you can connect the phone and glass via the myGlass app, so clearly, what I am looking to do is possible. However, I was wondering if someone could point me in the right direction to get started? Specifically, what technologies should I look at if not CoreBluetooth on the iOS side? Has anyone else done this?
Also, if it would be better served to use Bonjour, or even to create the hotspot on my iPhone and connect that way, any tutorials you could point me to would be great.
Thanks in advance.
I'm writing a Google Glass Development book for Apress and just finished the chapter Network and Bluetooth, with some working samples to let Glass communicate with iPhone for data transfer. You're right that Glass as of now (API level 15) doesn't support Bluetooth Low Energy (BLE). I have implemented three ways to make the data transfer between Glass and iOS happen:
Let Glass talk to an Android device, such as Nexus 7 with Android 4.3 or above with BLE support, via Classic Bluetooth or socket, and Nexus 7 acts as a BLE central to talk to iOS as a BLE peripheral. Notice you shouldn't use BLE to send large data such as photo.
Let Glass talk to iOS directly via socket - you can use C socket code running as a server and Glass Java socket client, or vice versa. This would require your Glass and iOS device on the same Wifi, but can transfer large data.
Use a server-based solution - upload data from Glass to a server and let iOS get it via Apple Push Notification. I used this method to share photos on Glass with friends on WhatsApp and WeChat, both apps run on iOS.
Sample iOS code acting as socket server:
- (void) runSocketServer {
int listenfd = 0;
__block int connfd = 0;
struct sockaddr_in serv_addr;
__block char sendBuff[1025];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(6682);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
int count = 1;
while (count++ < 120) {
char rate[100];
sprintf(rate, "%i\n", bpm);
write(connfd, rate, strlen(rate));
sleep(1);
}
close(connfd);
});
}
Sample Glass code acting as a socket client:
public void run()
{
String serverName = "192.168.1.11";
int port = 6682;
try
{
socket = new Socket(serverName, port);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
do {
result = input.readLine();
runOnUiThread(new Runnable() {
public void run() {
mTvInfo.setText(result);
}
});
} while (result != null);
});
}
catch(Exception e) {
try { socket.close(); }
catch (Exception e2) {};
e.printStackTrace();
}
}
Have you tried setting up Google backup? You can instantly get your pictures from glass and view them on your phone (but not vice versa).
Otherwise, there is currently no way on the market for this, but here are a couple of ideas:
You could submit it as an app idea to one of these:
http://glass-apps.org/google/glass-app-ideas
https://plus.google.com/communities/107405100380970813362/stream/b18a5f3c-e170-40a8-991f-823f018e75af
Or you could build it yourself. The GDK is pretty powerful. You can't submit gdk apps to Google yet, but it would be great for personal use. This guy started working on it and his github is here:
https://github.com/NathanielWaggoner/GoogleGlassBlutooth

Resources