fetchTimeEstimate not authorised - but strangely only on some iPhone's - ios

I'm using the Uber Rides iOS SDK and currently only interested only in how long an uber will take to arrive, we just launch the uber app to the app if the user wants to proceed.
Strangely on some iPhones and the simulator it returns a result pretty much always (unless no cars available), but on others it says not authorised as a response.
Here is the code for the call:
func fetchTimeEstimates(from location: CLLocation, completion: #escaping (_ estimate: TimeEstimate?) -> Void) {
ridesClient.fetchTimeEstimates(pickupLocation: location) { (estimates, response) in
if response.statusCode != 200 || estimates.isEmpty {
print("UBER fetchTimeEstimates returned \(response.statusCode)")
completion(nil)
return
}
// Set default to uberX
for i in 0...estimates.count - 1 {
if let id = estimates[i].productID, id == UberRides.uberXProductId {
completion(estimates[i])
return
}
}
completion(estimates[0])
}
}
Im using server token setup in my plist
Although it either consistently works or does not on peoples phones, It does not seem a consistent pattern, i.e. its not that the first 5 devices worked and then it stopped working after that, or type of phone or OS version.
Heres what I tried:
Adding a failing devices user to list of developers in the dashboard authorisation screen, no difference.
Requesting full api access for a 'request', nope
checking if a brand new phone 8 with brand new user credentials both for the phone and uber login, works fine so don't explain why we go two people in the office where its consistently refused.
adding the app ID in the developer console.
Any ideas why I'm getting inconsistent results, its a challenge to debug as it always works on my test phones, but annoyingly it fails consistently on the CEO's phone.

Related

IOS app to display values via BLE from an ESP32

I have an ESP32 Battery monitor system (BMS) whose status I want to view on an iPhone, there are about 100 values to be monitored with a maximum update rate of once per second. I also needs to be able to send settings to the BMS occasionally.
Blynk seemed to be the perfect app to do this but the new version 2.0 doesn't support BLE! Does anyone know a similar app that could do this?
Have you tried setting the ESP32 up as a web server and creating an API based on the values? Using this instead of bluetooth allows you to view the values from anywhere with internet connection, and is easier to implement and use across different platforms
You can do this by implementing code into the ESP32, so that when you make http requests, it returns with a value, just like any other API would. Then in Xcode where you are building your IOS app you can make http requests to the web server and retrieve values
for example, in the ESP32 you can do something like this (assuming you are using the Arduino IDE to program it):
server.on("/value", [](AsyncWebServerRequest * request))
{
String value = "value"
request->send(200,"text/plain", value)
}
This YouTube video shows you this in more detail: https://www.youtube.com/watch?v=cWZP7Y8qP6E
Then, in Xcode you can implement something along the lines of:
func loadData() async {
guard let url = URL(string: "http://IP-address-of-esp32/path-of-value", ) else {
print("Invalid URL")
return
}
do {
let (data, _) = try await URLSession.shared.data(from: url)
// process data here with the 'data' variable
} catch {
print("Invalid Data")
}
}
//Be aware that this is asynchronous when calling it
This person also explains it in more detail in a YouTube video: https://www.youtube.com/watch?v=MBCX1atOvdA
Now, since you have a web server and API set up on your ESP32, and a method of retrieving the values in your IOS app, you can go on and use the values to build the app to your liking.
Good Luck!

Google Home. Problem regarding configure a Lock device

Intro:
was created a Google Smart Home project
was configured a proxy server via ngrok to redirect the Google request to my local machine
I develop an IoT project that has the ability to open/close a lock. I need to implement Google integration to use the Google Assistant to control the user locks. I have implemented OAuth Server for Google. Also I have implemented some controllers to handle Google Action Intents: SYNC, QUERY and EXECUTE. Google send a request with the SYNC intent and App response a payload that contain devices list with specific settings. Instance:
{
requestId: 'requestIdOfGoogle', // contains in the request body
payload: {
agentUserId: 'userId123', // matches user id inside app system
devices: [
{
id: 1,
type: 'action.devices.types.LOCK', // device type
traits: ['action.devices.traits.LockUnlock'], // feature that has a device
name: {
name: 'Kos Lock'
},
willReportState: true,
roomHint: 'Main Door',
deviceInfo: { // Test data
manufacturer: 'smart-home-inc',
model: 'hs1234',
hwVersion: '3.2',
swVersion: '11.4'
}
}
]
}
}
Then Google send requests to my server with QUERY intent to get info about state of a devices, instance
{
requestId: 'requestIdOfGoogle', // contains in the request body
payload: {
devices: {
1: {
status: 'SUCCESS',
online: true,
isLocked: true,
// isJammed - Boolean. Whether the device is currently jammed and therefore its
// locked state cannot be determined.
isJammed: false
}
}
}
}
But after sending a response a test lock isn't configured and a user can't control one with Google Assistant.
enter image description here
I have tried to add other traits for a lock but it didn't help me. Also I have the same problem when I try to configure a Door device. But when I send to Google a Light device it works successfully. When you use the LockUnlock trait then Google Doc recommends to setup secondary user verification but it's optional.
I don't understand that do incorrect. If someone faced such a problem and solved it then could you help me, please
Prerequisites:
use node ^14.0.0
programming language - js
Touch controls are not supported for every device, and locks are not a device type that can be controlled directly. But they will still respond to voice commands.

ASAuthorizationController issue when working with multiple requests

So, here's the issue:
If I have both email-password and apple id records in my keychain for an app,
and want to request that data to do auto-login,
I can get email-password based accounts info fine.
Apple ID does not work as expected though.
I receive ASAuthorizationAppleIDCredential object with authorizationCode == nil.
I do receive credential.identityToken and can decode the token. It's a valid one, but the thing is that I need authorizationCode.
If I use stand-alone login function of AppleAuthenticator, it works correctly. ASAuthorizationController executes performRequests perfectly and I can get authorizationCode from ASAuthorizationAppleIDCredential.
The issue is with AggregatedAuthenticator. It seems that ASAuthorizationController is sort of broken and cannot get all the data if there's more than one request passed to it.
AggregatedAuthenticator(anchor: view.window!).startAutoLogin() // does not work with apple id
but
AppleAuthenticator(anchor: view.window!).login() // works
The only difference is that AppleAuthenticator uses only one request in ASAuthorizationController.
The only workaround that I could come up with is if I go to AggregatedAuthenticator and do the login again there, see the comment in code:
public func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
switch authorization.credential {
case let appleIDCredential as ASAuthorizationAppleIDCredential:
// Question: here we receive the credential without authorizationCode, but why?
appleAuthenticator.login(with: appleIDCredential)
// BUT if I do:
// appleAuthenticator.login()
// it works fine, but it shows that bottom sheet again asking for your face/touch-id again, but only for apple id this time
case let emailPasswordPair as ASPasswordCredential:
emailAuthenticator.login(with: emailPasswordPair)
default:
print("Irrelevant stuff")
}
}
Any ideas, folks?
Take a look at the sample code below:
https://github.com/SergeyPetrachkov/ASAuthControllerIssueSample
Alright, folks, it's an iOS 15 regression. Everything used to work before.

Firebase data retrieval sporadically not returning

I am building a project with Firebase that involves users. There is a known Firebase bug where even after a user has been deleted from the Firebase Authentication section, the user is still able to access the app and still has read/write permissions to the database. I believe it has something to do with the token being stored by Firebase on the user's device.
As a work around to this, I have implemented a "user checkup" where my app will check to see if the userID of the logged in user exists in my real-time database. This way all i have to do is delete the userID node from the real-time database and that will cause this checkup to fail and thus log the user out permanently.
The problem i am having is that the call to observeSingleEvent(of: .value...) is sporadically not returning. By this i mean that sometimes it returns immediately as is expected, however sometimes it just doesn't return at all. For example yesterday morning it wasn't working at all. Yesterday afternoon and night it worked fine. Now today it is no longer working again. Code below...
func checkDatabaseForFIRUser(withId: String, callback: #escaping (Bool)-> Void) {
let fireUsersRef = fireRootRef.child("all-users").child(withId)
fireUsersRef.observeSingleEvent(of: .value, with: {(snapshot)-> Void in
print("user check result -> \(snapshot)")
if snapshot.exists() {
print("SNAP EXISTS")
callback(true)
} else {
print("SNAP NOT EXISTS")
callback(false)
}
}, withCancel: {(error)-> Void in
print("CANCEL BLOCK ERROR = \(error) and localized description = \(error.localizedDescription)")
})
}
I have also noticed that during the times when I am unable to retrieve data I am also unable to write anything to the database, it is as if nothing at all works. My Firebase Rules have been set to "Public" so anyone can read/write. And I have a working internet connection on my device
EDIT: everything works fine on Simulator. Issue is only occurring on the actual device
EDIT #2: This issue seems to have subsided, I haven't noticed it for at least a few weeks now
I bet that by the time you are calling observeSingleEvent, you are log out, so probably that's why it is not returning anything.

Apple Store build rejected while using CloudKit/iCloud

I just submited my app to the Apple Store and it failed submission because of the following issue and I am quite confuse about how to work around it.
From Apple - 17.2 Details - We noticed that your app requires users to
register with personal information to access non account-based
features. Apps cannot require user registration prior to allowing
access to app content and features that are not associated
specifically to the user.
Next Steps - User registration that requires the sharing of personal
information must be optional or tied to account-specific
functionality. Additionally, the requested information must be
relevant to the features.
My app uses CloudKit to save, retrieve and share records. But the app itself do not ask for any personal details neither share any personal details like emails, names, date of birth..., it just asks the user to have an iCloud account active on the device. Then CloudKit uses the iCloud credentials in order to work.
It becomes confusing because:
1 - I can't change the way CloudKit works and stop asking for the user to login on iCloud. Every app that uses CloudKit needs an user logged on iCloud.
2 - As other apps (facebookas an example) if you do not login the app cannot fundamentally work. So the login is not tied to specific functionality, but to the whole functionality of the app.
The code example bellow is called on an initial screen (before getting inside the app functional areas) every time the app starts to make sure the user has the iCloud going. If the user has iCloud I take him inside the app. If not I stop him and ask him to get iCloud sorted. But I guess that is what they are complaining about here - "User registration that requires the sharing of personal information must be optional or tied to account-specific functionality. Additionally, the requested information must be relevant to the features.".
Which puts myself in a quite confusing situation. Not sure how to resolve the issue. Has anyone has similar issues with CloudKit/iCloud/AppStore Submission? Any insights?
iCloud check code bellow:
func cloudKitCheckIfUserIsAuthenticated (result: (error: NSError?, tryAgain: Bool, takeUserToiCloud: Bool) -> Void){
let container = CKContainer.defaultContainer()
container.fetchUserRecordIDWithCompletionHandler{
(recordId: CKRecordID?, error: NSError?) in
dispatch_async(dispatch_get_main_queue()) {
if error != nil
{
if error!.code == CKErrorCode.NotAuthenticated.rawValue
{
// user not on icloud, taki him there
print("-> cloudKitCheckIfUserIsAuthenticated - error fetching ID - not on icloud")
// ERROR, USER MUST LOGIN TO ICLOUD - LOCK HIM OUTSIDE THE APP
result(error: error, tryAgain: false, takeUserToiCloud: true)
}
print("-> cloudKitCheckIfUserIsAuthenticated - error fetching ID - other error \(error?.description)")
// OTHER ERROR, TRY AGAIN
result(error: error, tryAgain: true, takeUserToiCloud: false)
}
else
{
let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
publicDatabase.fetchRecordWithID(recordId!,
completionHandler: {(record: CKRecord?, error: NSError?) in
if error != nil
{
// error getting user ID, try again
print("-> cloudKitCheckIfUserIsAuthenticated - error fetching user record - Error \(error)")
// ERROR, TRY AGAIN
result(error: error, tryAgain: true, takeUserToiCloud: false)
}
else
{
if record!.recordType == CKRecordTypeUserRecord
{
// valid record
print("-> cloudKitCheckIfUserIsAuthenticated - fetching user record - valid record found)")
// TAKE USER INSIDE APP
result(error: error, tryAgain: false, takeUserToiCloud: false)
}
else
{
// not valid record
print("-> cloudKitCheckIfUserIsAuthenticated - fetching user record - The record that came back is not a user record")
// ERROR, TRY AGAIN
result(error: error, tryAgain: true, takeUserToiCloud: false)
}
}
})
}
}
}
}
Initially my application would ask the user to login to iCloud on launch screen. If the users did not have an iCloud account functional they would not be able to get inside the app.
Solution
Let the user get inside the app and click on the main sections. In fact the app was completely useless but the user could see it's odd empty screens without the ability to save or load anything. By the time they tried to load or save things I would prompt them the needed to login on iCloud to make the app usable.
Practical outcome
I don't think apple's change request added anything of value to the UX. In fact it just added complexity for the user to understand what he can do and what he cannot.
As an example Facebook locks the user outside if the user do not provide his personal details because without this data the application has absolutely no use and that is my case... You could arguably say the user should be able to get inside, but what he would see or do? Then you would have to cater for all the exceptions this UX builds and throw warnings for the user to fix the account issue everywhere on an annoying pattern of warnings.
So I am not sure "how" Facebook could get it approved and I could not.
Although I got the app approved I disagree Apple feedback improved the application in any way.

Resources