Beaconstac / NearBee-iOS-SDK

Beaconstac NearBee SDK for iOS
https://www.beaconstac.com
MIT License
1 stars 0 forks source link

Spoofing beacon location #5

Closed JoeyBodnar closed 5 years ago

JoeyBodnar commented 5 years ago

The beacons I need to detect are in the USA, but I am located in Thailand. I do not have a physical beacon with me. I have setup the app to get the notifications on the lock screen, and a developer in the US has tested this for me and verified that it works.

However, because I cannot receive notifications here, it is quite difficult to test the userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) method and perform the appropriate actions when the app is opened via the notification.

So my questions are

1) is there a way to spoof this beacon location so that I can receive notifications here? 2) if that isn't possible, I assume the correct way to access the info being sent in the payload is : let payload = response.notification.request.content.userInfo, correct? And then I would just use that dictionary and get any value being sent, such as let urlSent = payload["url"]?

Thank you

sachinmobstac commented 5 years ago
  1. You can't broadcast the Eddystone packets on iOS. You need to use Beacon Simulator app on Android phone to simulate the it. You need to configure Eddystone-UID and Eddystone-URL packets according to the values written on the hardware. You can get these values in our dashboard's beacon detail page.

  2. Yes, that's how you access the url of the notification, the key will be EddystoneURL. However, we don't recommend overriding the notification as the SDK adds few parameters on loading for analytics purpose.

JoeyBodnar commented 5 years ago

Alright I triedresponse.notification.request.content.userInfo["EddystoneURL"] and response.notification.request.content.userInfo["eddystoneURL"] but was told that the action in the notification callback did not occur (as seen in code below). Today I'm going to buy an android device so I can simulate the beacon location and hopefully this will go much smoother.

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let isNearBeeNotification = nearBee.checkAndProcessNearbyNotification(response.notification)
    if (isNearBeeNotification) {
        if let url = response.notification.request.content.userInfo["EddystoneURL"] as? String {
            openWebpage(with: url)
        } else if let url = response.notification.request.content.userInfo["eddystoneURL"] as? String {
            openWebpage(with: url)
        } else { // default for demonstration purposes
            openWebpage(with: "https://apple.com")
        }
        completionHandler()
    }
}
sachinmobstac commented 5 years ago

@JoeyBodnar, We will have a method which will simulate the notification behavior. Meanwhile, instead of buying a new Android phone you can simulate using Macbook as well. Here is the example.

JoeyBodnar commented 5 years ago

When will you have that method? I tried the example you gave, but it doesn't work on macOS Mojave, as one of the underlying packages does not support it yet. Is there anything in my code above that does not look correct?

If the notifications are being received, then when the user opens the app from the notification, the code above should be called, correct?

sachinmobstac commented 5 years ago

The below code is enough.

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let isNearBeeNotification = nearBee.checkAndProcessNearbyNotification(response.notification)
    if (isNearBeeNotification) {
        if let url = response.notification.request.content.userInfo["EddystoneURL"] as? String {
            openWebpage(with: url)
        } else { // default for demonstration purposes
            openWebpage(with: "https://apple.com")
        }
        completionHandler()
    }
}

However, why are you trying to open the URL on your own? You should allow the NearBee SDK to handle the code.

JoeyBodnar commented 5 years ago

oh, so I should only have completionHandler() inside there then, that is all (as exactly in the example in the readme)? I was a bit confused about how the process works--in traditions push notifications on iOS you have to get the info and then take the appropriate action, I didn't know NearBee would also open the url by default. If they do, then yes I would prefer to default to that.

sachinmobstac commented 5 years ago

Yes, my bad. You just checkAndProcessNearbyNotification and it handles the notification by opening the URL. You don't need to open the URL on your own.

JoeyBodnar commented 5 years ago

alright I will test this soon. thanks!

JoeyBodnar commented 5 years ago

ok I tested that but it still is not working. Should my NearBee delegate my AppDelegate class? Right now it is the main view controller that the user sees when they enter the app.

I temporarily have access to an android device for another few hours and have now downloaded the Beacon Simulator app. Previously you wrote:

"You need to configure Eddystone-UID and Eddystone-URL packets according to the values written on the hardware. You can get these values in our dashboard's beacon detail page."

When I open the beacon simulator app, I am given a screen, that asks me to choose which kind of beacon I want to broadcast:

beconsimulator

So I guess my question is, how can I make the app configure both Eddystone UID and Eddystone URL packets, if the configuration only allows to broadcast as 1 type?

JoeyBodnar commented 5 years ago

this is my current code for NearBee: https://gist.github.com/JoeyBodnar/69e95112914f78539677b9dcdf495163

it is getting notifications on the lock screen, so it should be configured correctly. just nothing happens when opening the notification on the phone.

JoeyBodnar commented 5 years ago

@sachinmobstac any idea if something is incorrect in my code?

sachinmobstac commented 5 years ago

@JoeyBodnar, what values did you configure on the simulated beacon?

JoeyBodnar commented 5 years ago

I chose the Eddystone URL option and just input a url to a website, like apple.com. But it was not able to pick it up.

For the Eddystone UID option, it wants input values of Instance ID and Namespace ID, as seen in this image: https://i.imgur.com/TN79GGE.jpg

The only 2 values I have access to are the serial number and ID, as written on the box. I'm not sure where to find Namespace ID or Instance ID.

sachinmobstac commented 5 years ago

@JoeyBodnar, do you have access to the dashboard?

JoeyBodnar commented 5 years ago

I do not, but I was sent screenshots of the dashboard by Ryan. The dashboard screenshot gives me a list of beacons with this info:

Screen Shot 2019-04-11 at 1 39 03 PM
sachinmobstac commented 5 years ago

@JoeyBodnar, They have to send the values related to the beacon, which looks like below.

Screenshot 2019-04-11 at 12 24 28 PM
JoeyBodnar commented 5 years ago

Alright I see now. I will ask for these details. thanks!

JoeyBodnar commented 5 years ago

ok I have received the proper values and am using the Beacon Simulator app, but my phone (iPhone X, iOS 12.1) cannot detect the beacons. I have input the correct values for the Namespace ID and Instance ID. here are my settings:

IMG_0132

@sachinmobstac What else do I need to do in the Beacon Simulator app?

sachinmobstac commented 5 years ago

@JoeyBodnar, Is the app configured to broadcast both URL and UID frames?

JoeyBodnar commented 5 years ago

I am not sure. I don't have access to the android device but will see about that when I have the android again.

actually now, I have the app opening the url when the notification is pressed--but instead of opening it in the app, the url is opened in Safari. Do you see anything in my code that would cause this to occur? https://gist.github.com/JoeyBodnar/69e95112914f78539677b9dcdf495163

I have everything setup the way it is in sample app, as far as I can tell.

JoeyBodnar commented 5 years ago

Also, the app is not detecting beacons if the app has been force closed. It only detects beacons if the app is running in the background. Is that the correct and expected behavior?

sachinmobstac commented 5 years ago

@JoeyBodnar, to detect beacons in the background the app requires Always Allow Location Permission and based on the region entry/exit and display wake up the SDK scans for the beacons. The SDK will not redirect to the Safari app and it uses the SafariViewController to show the notification, you will be still inside your app's sandbox.

JoeyBodnar commented 5 years ago

The app can detect them in the background, just not when the app is completely closed. For example, if you open the app and then press the Home button, it can detect the beacons. But if you turn your iPhone off completely, and do not open the app, then it does not detect the beacons.

And I was told it opened in the Safari app, outside the app sandbox, but I will ask for clarification from Ryan.

sachinmobstac commented 5 years ago

@JoeyBodnar, I missed a few things, can please go through the checklist to receive the notifications when the app is killed.

  1. You have enabled Location Updates under the background mode in capabilities.
  2. The app has Always Allow Permission.
  3. The notifications will be called only if it is new. If you have received the notifications previously, it won't pop up again.
  4. When the display wakes up, the SDK scans for the beacons.
  5. When you enter the beacon region again after an hour or so the SDK scans for the beacons.
JoeyBodnar commented 5 years ago

alright, I did not have (1) done, but it wasn't in the Sample project either, so I will add that in and see how it goes.

JoeyBodnar commented 5 years ago

I added that in, and then the notifications stopped arriving completely. No notifications when app is in the foreground, background, or app closed. I removed it and the notifications started coming again.

JoeyBodnar commented 5 years ago

Also this code leads to the SDK opening the Url outside the app, inside the Safari app:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let isNearBeeNotification = nearBee.checkAndProcessNearbyNotification(response.notification)
    if (isNearBeeNotification) {
        completionHandler()
    }
}

And this code leads to is being called inside the app sandbox, correctly:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let isNearBeeNotification = nearBee.checkAndProcessNearbyNotification(response.notification)
    if (isNearBeeNotification) {
       // nothing called here at all
    }
}

Is this the expected behavior?

sachinmobstac commented 5 years ago

@JoeyBodnar, I retested the sample app for the notification behavior. It never opened the Safari. Please share a screenshot for the same.

Also, since iOS relies on iBeacon protocol to wake the app in the background. You need to configure iBeacon packet. @rv888 please send the iBeacon related values (UUID, Major, Minor) to @JoeyBodnar. It is in the Hardware Details section of Beacon Detail Page.

rv888 commented 5 years ago

@sachinmobstac I sent this info to @JoeyBodnar . Does he need this static info just for testing purposes? Would be bad if he needs to know this info for all beacons when the app launches. There will be over 400 beacons I believe.

sachinmobstac commented 5 years ago

@rv888, Yes it's only for testing purposes. It should be done only for one beacon. The rest will be set properly.

JoeyBodnar commented 5 years ago

I am adding this code in:

let locationManager = CLLocationManager()
if let uuid = UUID(uuidString: "xxxxx") {
    let region = CLBeaconRegion(proximityUUID: uuid, major: CLBeaconMajorValue(00000), minor: CLBeaconMinorValue(00000), identifier: "beacon1")
    locationManager.startMonitoring(for: region)
}

Is this correct? Was not entirely sure what to do with those values, but from looking at tutorials looks like I need to add them to a monitoring region?

sachinmobstac commented 5 years ago

No, the SDK automatically configures everything. You don’t need to write any code. Just transmit the iBeacon packet with proper values using Beacon Simulator app.

JoeyBodnar commented 5 years ago

ohhhhh ok I see. The values of UUID, Major, and Minor are for simulating the beacon location. I thought you were relating it to the ability to wake the app up in the background.

sachinmobstac commented 5 years ago

@JoeyBodnar, Did you test this out?

JoeyBodnar commented 5 years ago

Not yet, have not had access to an android device.

sachinmobstac commented 5 years ago

@JoeyBodnar, when can we close this?

JoeyBodnar commented 5 years ago

I think it can be closed. I have not been able to successful simulate the beacon location yet, but it looks like we got what we needed without needing to do so.