I am testing out using the Firebase SDK for iOS/macOS in my app (macOS app). i have installed the SDK´s using:
pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :tag => '4.8.2'
pod 'FirebaseAuth', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :tag => '4.8.2'
pod 'FirebaseStorage', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :tag => '4.8.2'
The installation works well and I can configure my app in AppDelegate using [FIRApp configure];
I wonder if I can use the SDK to log in the user to his/hers private Google Cloud storage (GCS)? I understand I can use the SDK for storing to GCS in the apps storage, but it would be nice to log in to the users own GCS to retrieve a list of buckets and files. If anyone has an example as for how to do this I would appreciate it. All examples I find are for anonymous storage logins.
Update:
I could specify that I was hoping that Firebase SDK would contain an authentication method that allowed me access to my own Google cloud storage account. Perhaps Firebase is not the right choice for this, but then I would be very interested in suggestions for alternative SDKs for Swift/objective-c login/upload/download to Google cloud storage.
You can indeed use the Firebase SDK for iOS to work with Firebase Cloud Storage (which in fact stores data in Google Cloud Platform Cloud Storage's buckets), using both Swift and Objective-C.
Firebase Cloud Storage in iOS
Regarding the usage of Cloud Storage buckets in your Firebase application, you can get started with this documentation page. First of all, you have to set up the proper security rules to the bucket: you can allow public access, access to only authenticated users, or even per-userID access. There are some sample rules that you can use to start working with this.
Once you have set up the appropriate access for Storage buckets (if each user has its own bucket, then I assume each user will have a GCP account with a private bucket and they will have to set up the configuration access themselves, as you will not have access to them), you can add the Cloud Storage dependencies to your iOS app:
pod 'Firebase/Core'
pod 'Firebase/Storage'
Then run pod install and you can already create the reference to Cloud Storage after initializing Firebase in your app (here you have a Swift sample code, but you can have a look at the Objective-C samples in the documentation too):
// Import and set up Firebase
import Firebase
FirebaseApp.configure()
// Create a storage reference
let storage = Storage.storage()
let storageRef = storage.reference()
// Refer to a child directory or even a file
let folderRef = storageRef.child("my_folder")
var fileRef = folderRef.child("my_file.txt")
And once you have all this, you can proceed to more complex guides, such as uploading files, downloading files or (important) handling errors. Bear in mind that these are just some examples of the things you can do following the step-by-step documentation, but feel free to move through all the pages in order to have a deeper understanding about how all this works.
Firebase Authentication for Cloud Storage in iOS
Also, regarding authentication, you can follow the same rules that you are probably already using for the rest of your Firebase application. Let me share this other page talking about some mechanisms to provide Firebase Authentication, and specifically how to provide Firebase Authetication on iOS.
I'm not sure I fully understand what you're asking. But if I do... This may help. I've used Google Storage to save photos. To access those photos I needed to store the URL to locate those photos. I did this in the Firebase Realtime Database. If you store a different type of file to a GCS, all you need is that URL to retrieve the data.
if let photoData = UIImageJPEGRepresentation(jpegRepresentation!, 1.0) {
storePhoto(photoData, angel.name!, completion: { (url, err) in
if err != nil {
print(err?.localizedDescription)
angelToSave["photo"] = nil
myAngelsRef.updateChildValues(angelToSave, withCompletionBlock: { (error, ref) in
if error != nil {
completion(error!)
} else {
completion(nil)
}
})
} else {
// ### HERE ####
angelToSave["photo"] = url?.absoluteString
angelNameRef.updateChildValues(angelToSave)
completion(nil)
}
})
}
func storePhoto(_ photo: Data, _ name: String, completion: #escaping (_ result: URL?, _ error: NSError?) -> Void) {
let storageRef = Storage.storage().reference().child(name)
storageRef.putData(photo, metadata: nil) { (storageMetaData, err) in
if err != nil {
completion(nil, NSError(domain: (err?.localizedDescription)!, code: 0, userInfo: nil))
} else {
completion(storageMetaData?.downloadURL(), nil)
}
}
}
After I saved the photo I was able to get the URL location and save that to an object I stored in the RTDB. Now when I pull the data from the use's RTDB I get the URL for the Storage data.
Related
I have made an app that requires login authorization, and I want each user who has signed up for the app to have their own folder in the firebase storage. That way, all the data that gets passed to firebase is organized in separate folders for each user; keeping everything organized and the data easily accessible. I am wondering how to do this but am lost. I currently have firebase set up for my app but am struggling to figure this part out.
To allow users to only read/write their own files, have a look at the section on content-owner only access in the documentation on security rules.
to upload files to a user-specific folder, start by setting up a reference to the user folder:
let storageRef = storage.reference()
if Auth.auth().currentUser != nil {
let uid = Auth.auth().currentUser.uid
let userRef = storageRef.child()
...
And then follow the rest of the documentation on uploading files.
I am trying to enable Facebook authentication in Realm Sync, but keep getting an error on login.
I have been using these guides:
https://docs.realm.io/sync/v/3.x/using-synced-realms/user-authentication/additional-providers#facebook
https://docs.realm.io/sync/v/3.x/self-hosted/customize/authentication/included-third-party-auth-providers/facebook-authentication
I have the Access Token provided by the Facebook API/SDK enabling me to log in/sign up a user.
When I use Realm's libraries to log in a user with the Facebook Access Token, I get an error stating the 'provider' parameter is invalid, but this parameter is defined by Realm's own classes.
I have successfully authenticated a user with an email & password so do I need to set up something else on Facebook/Realm Sync? It seems Facebook authentication just doesn't work in Realm Sync and the above help files are pretty useless.
Authentication code
func authenticateWithFacebook(facebookToken: String, completion: #escaping (RealmAuthenticationResult) -> ()) {
let credentials = SyncCredentials.facebook(token: facebookToken)
print("------FACEBOOK LOGIN-------")
print("Token: \(facebookToken)")
login(credentials) { (result, userId) in
completion(result)
}
}
private func login(_ credentials: SyncCredentials, completion: #escaping (RealmAuthenticationResult, String?) -> ()) {
SyncUser.logIn(with: credentials, server: RealmConnection.AUTH_URL, onCompletion: { (user, err) in
if let _ = user {
print("User has logged in/signed up")
return completion(RealmAuthenticationResult.success(true), user?.identity)
} else if let error = err {
print(error.localizedDescription)
return completion(RealmAuthenticationResult.failure(error), user?.identity)
}
})
}
The error
Error Domain=io.realm.sync.auth Code=601 "Your request parameters did
not validate. provider: Invalid parameter 'provider'!;"
UserInfo={NSLocalizedDescription=Your request parameters did not
validate. provider: Invalid parameter 'provider'!;}
Other things I have tried
I have tried directly instantiating the base provider class 'RLMIdentityProvider' and creating SyncCredentials with that, but no dice.
A workaround is to get the account information from the Facebook API/SDK and use the account's email to login/signup with a username/password setup. However, it seems to make Facebook authentication redundant.
That Realm Documentation link is outdated. See the 3.16.0 Documentation (or later) as a lot was changed.
At the moment Password, JWT & Firebase are the only auth options with Firebase Authentication being a very solid solution. Integrating Firebase is also covered in the Realm Documentation in the Using Sync'd Realms -> Authentication section. I won't link it as the documentation is being frequently updated now days.
As stated by the Realm Team (several times) extensive auth options are not a priority as other companies (like Firebase) handle it very well.
There were a number of posts on the Realm forums speaking to this but Ian's response to this question is very succinct.
we have and will continue to prioritize synchronization features for
mobile
and then
This is why we recommend that a production app should outsource user
management and authentication to a company which specialized in these
features.
I am using firebase in an iOS-Swift project in which I have to enable offline support for uploading posts, in the post there is a picture and caption just like Instagram, so what I want is when user is offline and he/she wants to upload a post, his/her picture get saved in cache and when user comes online that photo get uploaded and give back a download url that we can use for saving posts-details it in database.
sample code is:
let photoIDString = UUID().uuidString
let storageRef = Storage.storage().reference(forURL: "storage ref URL").child("posts").child(photoIDString)
storageRef.putData(imageData, metadata: nil, completion: { (metadata, error) in
guard let metadata = metadata else {
return
}
if error != nil {
return
}
storageRef.downloadURL(completion: { ( url, error ) in
guard let downloadURL = url else {
return
}
let photoUrl = downloadURL.absoluteString
self.sendDataToDatabase(photoUrl: photoUrl)
})
}
)
I want to know what changes should I make in my code to provide the offline capability. Any code snippet will help more.
The problem is better view as re-send to server when there is an error.
For your offline case, you can check if the error return is a network error, or manually check network connection availability.
You can create a re-send array of object
e.g
var resendList : [YourObjectType]
// when failed to send to server
resendList.append(yourFailedObject)
And then, 2 solutions:
Check the network connectivity manually and reupload in when the app become active in func applicationDidBecomeActive(_ application: UIApplication) in appDelegate. For checking connectivity you can try the method here: Check for internet connection with Swift But this has a problem that, the user has to go out the app and back again with network connected
Keep track(listen to notification) on the connectivity change, using a suggestion method by https://stackoverflow.com/a/27310748/4919289 and reupload it to server
and loop through all objects in resendList and re-upload again.
I am not an iOS developer, but I can share logical flow and some references.
When user clicks on upload: Check if network is available?
if yes: upload the post.
if no:
save the post to app storage or offline database
set broadcast receiver to receive broadcast when device comes online. This link may be helpful.
upload post when device comes online.
If you are looking for solution that is offered by Firebase, you may find more details here.
Firebase offers you plenty of ways to do this in their documentation. https://firebase.google.com/docs/database/ios/offline-capabilities
When uploading to the firebase server, it will queue itself and wait until it has a internet connection again to upload. If this happens to timeout or you want to do it your own way just attempt to upload with a completionHandler on the setValue or updateChild functions - if not successfully and the error message is because of internet, add it to a local cache to the phone with the data and the path to the firebase server.
onLoad, attempt the same upload again until it succeeds, once it succeeds - clear the local cache.
I am struggling with a problem for a while now.
I am using FireStore Database in my Swift project.
Here is my sample fragment of code:
db.collection("XXXX").whereField("XXXX", isEqualTo: XXX).getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
// SUCCESFULL
}
The thing is that, in my database, currently I do not have any Rules implemented. So it is not secure. I want to implement to my swift project so that I can modify the rules on my database.
I do not understand how to enable Authentication for my swift project.
In the Nature of my project, there is no user authentication needed by the users who is willing to use the application.
How can I implement authentication just before the database query in the code, so that the rules on my database satisfies.
The authentication must be independent on the users since there is no authentication mechanism exists in my swift projects since I do no need the users to authenticate in the app.
Can you share a simple authentication code or something so that I can use in my project ?
I tried to read the docs on google but they are all related to User Authentication Methods such Facebook, Email/Password, SMS .. etc
Thank you in Advance Guys
My app uses Firebase messaging and Google analytics. I am using this code to setup GAI:
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
if let error = configureError {
print("Error configuring Google services: \(error)")
}
let gai = GAI.sharedInstance()
gai?.optOut = true
gai?.trackUncaughtExceptions = true
gai?.logger.logLevel = GAILogLevel.verbose
gai?.dispatchInterval = 120
_ = gai?.tracker(withTrackingId: FWKeys.googleTrackingID)
but on this step console says that I am using Firebase analytics instead:
<FIRAnalytics/INFO> Firebase Analytics enabled
Google analytics console doesn't show any active users when I start the app. Why is this happening?
UPD: For some reason information in the Analytics console started updating. But I am still wondering why there is "Firebase Analytics enabled" in the log while I am setting up GAI.
When you use any Firebase feature, such as Firebase Cloud Messaging in your case, the Firebase SDK also enabled Firebase Analytics. This does not replace Google Analytics, it is an additional analytics solution on top.
To disable Firebase Analytics, see the instructions in this answer: How to disable/remove FirebaseAnalytics.