Fetch Google profile image url by UID - ios

I want to fetch the google profile image when UID is given to me .
I have this reference but m getting how to hit this url .
Please anyone provide me some example.
EDIT:
Here is my code
var googleImageUrl: URL?{
let urlString = "https://www.googleapis.com/plus/v1/people/\(uid)?fields=image&key=AIzaSyBfjHpl8DjU0IGw9mXbvK6HoNpY"
return URL(string: urlString)
}
Alamofire.request(url)
.validate()
.responseJSON(completionHandler: { (response) in
if response.result.isSuccess {
let json = response.result.value as? [String: Any]
} else {
let apiError = ApiError(response: response)
}
})
when hitting this api, am always getting the error. Why i am not getting the response ?

You have two options:
Using Googles API, requires API key:
https://www.googleapis.com/plus/v1/people/{UID}?fields=image&key={YOUR_API_KEY}
Using Googles Picasaweb which does not require any API key:
http://picasaweb.google.com/data/entry/api/user/{UID}?alt=json
Code to get the image:
// Check what you want to return in the onCompletion and use it
func getImage(uid: String, onCompletion: #escaping (String) -> Void, onError: #escaping (NSError) -> Void) {
let url = "https://www.googleapis.com/plus/v1/people/\(uid)?fields=image&key=AIzaSyBfjHpl8DjU0IGw9mXbvK6HoNpY"
let headers = [
"Content-Type": "application/json"
]
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
if let object = response.result.value as? [String:Any] {
print(object)
// use the onCompletion in here
}
}
}

The reference you listed points to the Google People API, which is different than the Google+ People API. If you want to use the Google People API you should use https://people.googleapis.com/v1/people/{UID}?personFields=photo&key={YOUR_API_KEY}
There are official examples at: https://developers.google.com/people/v1/read-people#get-the-person-for-a-google-account

Related

Send image from iOS Alamofire to Vapor

I have an application where user can update their profile picture.
The application is developed in SwiftUI and used Alamofire to perform API request and the server is developed with Vapor.
When I tried to send the picture to the server, I got this error:
[ WARNING ] Value required for key 'filename'. [request-id: A5083FA1-657C-4777-A7FF-9D02E2A66703]
Here is the code from Vapor:
private func updatePicture(req: Request) async throws -> Response {
let file = try req.content.decode(File.self)
guard let fileExtension = file.extension else { throw Abort(.badRequest)}
return .init(status: .accepted, headers: getDefaultHttpHeader(), body: .empty)
}
And here is the iOS code:
func uploadFiles(urlParams: [String], method: HTTPMethod, user: User, image: UIImage, completionHandler: #escaping ((Data?, HTTPURLResponse?, Error?)) -> Void) {
guard let formattedUrl = URL(string: "\(url)/\(urlParams.joined(separator: "/"))") else {
completionHandler((nil, nil, nil))
return
}
var headers: HTTPHeaders?
headers = ["Authorization" : "Bearer \(user.token)"]
let multiPart: MultipartFormData = MultipartFormData()
multiPart.append(image.jpegData(compressionQuality: 0.9), withName: "data", fileName: "filename", mimeType: "image/jpeg" )
AF.upload(multipartFormData: multiPart, to: formattedUrl, method: .patch, headers: headers).response { data in
print(data)
}.resume()
}
I followed vapor and Alamofire documentation and I still get this issue.
Is anyone can help me with this issues ?
On the Vapor side you have to use struct with File field inside
struct PayloadModel: Content {
let data: File
}
private func updatePicture(req: Request) async throws -> HTTPStatus {
let payload = try req.content.decode(PayloadModel.self)
guard let fileExtension = payload.data.extension else {
throw Abort(.badRequest)
}
return .accepted
}

POST profile image to Laravel server using Alamofire

Im trying to upload a file to the backend. edit
I'm at a stand still with this code. I feel like I'm doing this wrong. Its returning (Status Code: 400, Headers ) Which makes me believe that the error is in the headers but I may be totally wrong because I see people using .upload() instead of .request. I've made 2 functions based on these two methods, neither one works. .request is error 400, upload() is error 500. I've tried the access token in L5 Swagger and it works. The only parameter is a file which I assume is data. Here are the methods
#discardableResult
public func postUploadSeekerAvatar(_ image: UIImage, result: #escaping (Error?) -> Void) -> URLSessionTask? {
let imageData: Data = UIImagePNGRepresentation(image)!
let params: [String: Any] = ["data": imageData]
var headers = authHeader
headers?["Content-Type"] = "application/json"
return Alamofire.request(endpointURL("users/seeker/avatar"), method: .post, parameters: params, headers: headers)
.responseData(completionHandler: { (response: DataResponse<Data>) in
guard response.result.error == nil else {
return result(response.result.error)
}
return result(response.result.error)
}).task
}
#discardableResult
public func postSeekerAvatar(_ image: UIImage, result: #escaping (Error?) -> Void) -> URLSessionTask? {
let data = UIImagePNGRepresentation(image)!
var headers = authHeader
headers?["Content-Type"] = "application/json"
return Alamofire.upload(data, to: endpointURL("users/seeker/avatar"), method: .post, headers: headers)
.responseData(completionHandler: { (response: DataResponse<Data>) in
guard response.result.error == nil else {
return result(response.result.error)
}
return result(response.result.error)
}).task
}
Can you sirs and madams please help a newbie? Thank you!

FAILURE: responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)

I'm trying to read the JSON using Alamofire. Here is my code:
let headers = ["Content-Type": "application/json"]
func getConfirmationCode(params: [String:Any], block: #escaping(_ data : JSON, _ success : Bool) -> Void) {
if let url = URL(string: baseURL + "getConfirmationCode.php") {
Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
DispatchQueue.main.async {
if let value = response.result.value {
let json = JSON(value)
block(json, true)
} else {
block(JSON.null, false)
}
}
}
}
}
The JSON is valid, everything works perfectly in Postman, but I can't make it work. None of the suggestions on the web helped (changing the responseJSON to responseString/responseData, changing the JSONEncoding.default to URLEncoding.default, etc.)
Can anyone help me?
You should try to check response in postman in "Preview" tab of response section. sometime it displays proper json in "Pretty" section. but in "Preview" section it many contains some print statements of API response. and those print statements makes problem in json decoding.
also, if you want to get swift code of postman response you can always get it from postman's code feature:
Hope this helps..!

Google translate api, Requests from this ios client application \u003cempty\u003e are blocked

I got this error message "Requests from this ios client application \u003cempty\u003e are blocked" by calling translate api, I have set to ios app and my bundle id on the web. Please help
let TRANSLATE_API = "https://translation.googleapis.com/language/translate/v2"
let GOOGLE_CLOUD_API_KEY = "<API_KEY>"
let urlParams:[String : Any] = [
"target": target,
"q": textToTranslate,
"key": GOOGLE_CLOUD_API_KEY,
"source": source]
let bundleIdentifier = Bundle.main.bundleIdentifier!
let headers:[String : String] = ["Content-Type": "application/json", "X-Ios-Bundle-Identifier": bundleIdentifier]
// Fetch Request
let urlString = TRANSLATE_API
// Fetch Request
Alamofire.request(urlString, parameters: urlParams)
.validate()
.responseJSON { (response) in
switch(response.result) {
case .success(_):
if response.result.error != nil {
completion(false, response.result.error! as! String)
}
if let json = response.result.value as? [String: Any] {
if let data = json["data"] as? [String: Any] {
if let translations = data["translations"] as? [[String:Any]] {
let translatedTextDict = translations[0]
if let result = translatedTextDict["translatedText"] as? String {
completion(true, result)
}
}
}
}
break
case .failure(_):
completion(false, (response.result.error?.localizedDescription)!)
break
}
}
I ran into the same problem, and after debugging, I found out the problem,
the API key works if you add it to the url, so the change your request to something like:
let BASE_URL = URL(string: "https://translation.googleapis.com/language/translate/v2")!
Alamofire.request(BASE_URL, method: .post, parameters: params, encoding: URLEncoding.default, headers: nil)
I don't know why removing the header "Content Type" affects it.
Also a Tip: never share your keys publicly, and don't put it like that in your code, especially if you're hosting it on a public repository. Put it in a gitignored file and read it when your app starts, or set an environment variable.
Let me know if you have follow up questions.

Swift 3 reusable post method in helper

I am working on swift 3 application and want to build login system using REST API. First I wanted a way to post data to server (PHP + MYSQL) with parameters so I found this post.
HTTP Request in Swift with POST method
Now I wanted place this code in a method as helper so I can utilise this method from anywhere in app. Hence followed this way:
Where to put reusable functions in IOS Swift?
Current code is as follow:
import Foundation
class Helper {
static func postData(resource: String, params: [String: String]) -> [String:String] {
var request = URLRequest(url: URL(string: "http://localsite.dev/api/\(resource)")!)
request.httpMethod = "POST"
var qryString: String = "?key=abcd"
for (paramKey, paramVal) in params {
qryString = qryString.appending("&\(paramKey)=\(paramVal)")
}
request.httpBody = qryString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("Error")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("Error on HTTP")
return
}
let responseString = String(data: data, encoding: .utf8)
print("success and here is returned data \(responseString)")
}
task.resume()
return ["data" : "some data"]
}
}
Call this using
let loginDetails: [String: String] = ["email": emailTxt.text!, "pass": passTxt.text!]
Helper.postData(resource: "login", params: loginDetails)
In above method rather then printing data I want to return data as per below 4 conditions.
1.If error in request data then I want to return as
[“status”: false, “message”: “Something wrong with request”]
2.If error in HTTP request
[“status”: false, “message”: “Resource not found”]
3.If login fail
[“status”: false, “message”: “Wrong login details”]
4.If login success
[“status”: true, “message”: “Login success”]
If you want to use a third party library for handling HTTP request, I strongly recommend Alamofire.
When I wanna handle HTTP requests I usually create a singleton class:
class HttpRequestHelper {
static let shared = HttpRequestHelper()
func post(to url: URL, params: [String: String], headers: [String: String], completion: (Bool, String) -> ()){
//Make the http request
//if u got a successful response
// parse it to JSON and return it via completion handle
completion(true, message)
//if response is not successful
completion(false, message)
}
}
And you can use it everywhere:
class AnotherClass: UIViewController {
HttpRequestHelper.shared.post(to: url, params: [:], header: [:],
completion:{
success, message in
print(success)
print(message)
})
}
To the POST method more reusable and not just specific to an endpoint, I usually make the completion handler params as Bool, JSON. And then I handle the JSON response from wherever I call the method.
Oh and I use SwiftyJson to parse json, it's the simplest.

Resources