How to retrieve Avatar images of users in Quickblox - blob

I am using Quickblox API and successfully uploading, fetching and retrieving the Avatar image of the user.But in my app i want to show the list of users when a user logs in. How to get the users avatars.
I am getting the list of users (QBUsers) but in that BlobId is Null for everyone, though Avatar images are existing for the users.
Please help me for fetching avatars of the users.

func downloadTeamMemberAvatar(avatarFileId:String,completion: (UIImage?)->Void){
let id = UInt(avatarFileId)
if let _ = id{
QBRequest.downloadFileWithID(id!, successBlock: { (_, imageData) in
let image = UIImage(data:imageData)
completion(image)
}, statusBlock: { (_, _) in
}, errorBlock: { (_) in
completion(nil)
})
}else{completion(nil)}
}

Related

How to correctly display image in Kotlin from firebase storage and firestore

I'm working on a project that use Firebase Storage and Firestore. I added function that allows to upload images from phone gallery to Storage and storage url of this image is saved in Firestore with some other informations. Everything works fine, even the image url in firestore displays selected image correctly in browser. The problem is when i try to set this image to ImageView using Glide or Picasso, because it only shows a blank image/placeholder. This is how my repository functions looks to add and download data:
override fun addProject(uri: Uri, project: Project) {
val imagesRef = storage.reference.child("images/${uri.lastPathSegment}")
Log.d("firebase ref url", imagesRef.toString())
imagesRef.putFile(uri).addOnCompleteListener {
Log.d("firebase image", "Succesfully uploaded")
imagesRef.downloadUrl.addOnSuccessListener { uri->
project.photoUrl = uri.toString()
db.collection("projects").add(project)
}
}.addOnFailureListener {
Log.d("firebase image", "Unsuccessfully uploaded")
}
}
override suspend fun getProjects(): List<Project> {
val projectList = mutableListOf<Project>()
val projectRef = db.collection("projects")
val snapshot = projectRef.get().await()
val docs = snapshot.documents
docs.forEach {
val project = it.toObject(Project::class.java)
if (project != null) {
projectList.add(project)
Log.d("firebase listen", projectList.toString())
}
}
return projectList
}
firebase storage
firebase firestore
After i retrieve all projects with their photoUrl and other informations i want to display them in recycler view using ListAdapter. Title and description are displayed correctly in every recycler view item but it seems like this url can't be accessed by glide/ picasso . There is also a log line which shows photoUrl and if I click on it from logcat the browser displays correct image.
fun bind(project: Project) {
binding.apply {
Log.d("recycler view url", project.photoUrl)
// Picasso.get().load(project.photoUrl).into(projectIv)
Glide.with(binding.root).load(project.photoUrl).into(projectIv)
titleTv.text = project.name
descriptionTv.text = project.description
}
binding.executePendingBindings()
}
I have found some related topics but still haven't found working solution to that problem.
EDIT
Log result inside recyclerview bind method:
Log resylt
After clicking on link:
Link result
How it looks in my app:
app screenshot 1
app screenshot 2
It looks like it only takes the photo size parameters but can't resolve the photo content, but i'm not sure

Agora Web SDK Screen share not returning video track

I have integrated Screen Share function on my web conference and Screen Share content will show on users who are in the session before Screen Share start, but it does not work on user who have joined the session after the Screen Share have started.
Below is the logic for getting video tracks when new user join the session.
// Add current users
this.meetingSession.remoteUsers.forEach(async ru => {
if (ru.uid.search('screen_') > -1) {
this.getScreenShare(ru);
return;
}
let remoteVideo = await this.meetingSession.subscribe(ru, 'video');
this.setVideoAudioElement(ru, 'video');
let remoteAudio = await this.meetingSession.subscribe(ru, 'audio');
this.setVideoAudioElement(ru, 'audio');
})
async getScreenShare (user) {
...
this.currentScreenTrack = user.videoTrack;
// Here user.videoTrack is undefined
console.log(user)
...
},
After the new user's session is created, I'm getting the current user's video track from "remoteUsers" object inside session object. No problem with regular user's video track, but Screen Share object say "hasVideo" is true but "videoTrack" is undefined.
Agora Web SDK meetingSession.remoteUsers Screen Share Object
Is this a specification that videoTrack is not included in meetingSession.remoteUsers for Screen Share?
I'm wondering what method people are using to show Screen Share content for user who have joined the session during Screen Share.
It will be great if someone can give me suggestion about this.
"agora-rtc-sdk-ng": "^4.6.2",
I had it figured out.
I just needed to subscribe the remote user.
this.meetingSession.remoteUsers.forEach(async ru => {
if (ru.uid.search('screen_') > -1) {
// Just needed to subscribe the user...
await this.meetingSession.subscribe(ru, 'video');
this.getScreenShare(ru);
return;
}
let remoteVideo = await this.meetingSession.subscribe(ru, 'video');
this.setVideoAudioElement(ru, 'video');
let remoteAudio = await this.meetingSession.subscribe(ru, 'audio');
this.setVideoAudioElement(ru, 'audio');
})

A better way to handle async saving to backend server and cloud storage from React Native app

In my React Native 0.63.2 app, after user uploads images of artwork, the app will do 2 things:
1. save artwork record and image records on backend server
2. save the images into cloud storage
Those 2 things are related and have to be done successfully all together. Here is the code:
const clickSave = async () => {
console.log("save art work");
try {
//save artwork to backend server
let art_obj = {
_device_id,
name,
description,
tag: (tagSelected.map((it) => it.name)),
note:'',
};
let img_array=[], oneImg;
imgs.forEach(ele => {
oneImg = {
fileName:"f"+helper.genRandomstring(8)+"_"+ele.fileName,
path: ele.path,
width: ele.width,
height: ele.height,
size_kb:Math.ceil(ele.size/1024),
image_data: ele.image_data,
};
img_array.push(oneImg);
});
art_obj.img_array = [...img_array];
art_obj = JSON.stringify(art_obj);
//assemble images
let url = `${GLOBAL.BASE_URL}/api/artworks/new`;
await helper.getAPI(url, _result, "POST", art_obj); //<<==#1. send artwork and image record to backend server
//save image to cloud storage
var storageAccessInfo = await helper.getStorageAccessInfo(stateVal.storageAccessInfo);
if (storageAccessInfo && storageAccessInfo !== "upToDate")
//update the context value
stateVal.updateStorageAccessInfo(storageAccessInfo);
//
let bucket_name = "oss-hz-1"; //<<<
const configuration = {
maxRetryCount: 3,
timeoutIntervalForRequest: 30,
timeoutIntervalForResource: 24 * 60 * 60
};
const STSConfig = {
AccessKeyId:accessInfo.accessKeyId,
SecretKeyId:accessInfo.accessKeySecret,
SecurityToken:accessInfo.securityToken
}
const endPoint = 'oss-cn-hangzhou.aliyuncs.com'; //<<<
const last_5_cell_number = _myself.cell.substring(myself.cell.length - 5);
let filePath, objkey;
img_array.forEach(item => {
console.log("init sts");
AliyunOSS.initWithSecurityToken(STSConfig.SecurityToken,STSConfig.AccessKeyId,STSConfig.SecretKeyId,endPoint,configuration)
//console.log("before upload", AliyunOSS);
objkey = `${last_5_cell_number}/${item.fileName}`; //virtual subdir and file name
filePath = item.path;
AliyunOSS.asyncUpload(bucket_name, objkey, filePath).then( (res) => { //<<==#2 send images to cloud storage with callback. But no action required after success.
console.log("Success : ", res) //<<==not really necessary to have console output
}).catch((error)=>{
console.log(error)
})
})
} catch(err) {
console.log(err);
return false;
};
};
The concern with the code above is that those 2 async calls may take long time to finish while user may be waiting for too long. After clicking saving button, user may just want to move to next page on user interface and leaves those everything behind. Is there a way to do so? is removing await (#1) and callback (#2) able to do that?
if you want to do both tasks in the background, then you can't use await. I see that you are using await on sending the images to the backend, so remove that and use .then().catch(); you don't need to remove the callback on #2.
If you need to make sure #1 finishes before doing #2, then you will need to move the code for #2 intp #1's promise resolving code (inside the .then()).
Now, for catching error. You will need some sort of error handling that alerts the user that an error had occurred and the user should trigger another upload. One thing you can do is a red banner. I'm sure there are packages out there that can do that for you.

appleAuthRequestResponse returning null for fullName and email

I am confused why me below snippet of code is showing null for email and fullName in console after user is authenticated successfully. I have read the documentation carefully and tried every possible thing I could. Any help would be highly appreciated.
async function onAppleButtonPress() {
// performs login request
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: AppleAuthRequestOperation.LOGIN,
requestedScopes: [AppleAuthRequestScope.EMAIL, AppleAuthRequestScope.FULL_NAME],
});
//api getting current state of the user
const credentialState = await appleAuth.getCredentialStateForUser(appleAuthRequestResponse.user);
if (credentialState === AppleAuthCredentialState.AUTHORIZED) {
// user is authenticated
console.log("email is",appleAuthRequestResponse.email);
console.log("full name is",appleAuthRequestResponse.fullName);
}
}
You can still retrieve the e-mail from the identityToken provided by appleAuthrequestResponse with any jwt decoder like jwt-decode
const {identityToken, nonce, email} = appleAuthRequestResponse
const {email} = jwt_decode(identityToken)
console.log(email)
Apple only returns the full name and email on the first login, it will return null on the succeeding login so you need to save those data.
To receive these again, go to your device settings; Settings > Apple ID, iCloud, iTunes & App Store > Password & Security > Apps Using Your Apple ID, tap on your app and tap Stop Using Apple ID. You can now sign-in again and you'll receive the full name and `email.
Source here.

Getting LinkedIn Profile Picture

Is there an easy way to grab a users LinkedIn profile photo?
Ideally similar to how you would with Facebook - http://graph.facebook.com/userid/picture
You can retrieve the original photo size with this call:
http://api.linkedin.com/v1/people/~/picture-urls::(original)
Note that this could be any size, so you'll need to do scaling on your side, but the image is the original one uploaded by the user.
Not as easy... You need to go through OAuth, then on behalf of the member, you ask for:
http://api.linkedin.com/v1/people/{user-id}/picture-url
If you use the 2.0 version of the API (all developers need to migrate by March 1, 2019), you should use projections to expand the profilePicture.displayImage. If you do this, you will have a full JSON element displayImage~ (the '~' is not a typo) inside profilePicture with all the info you may need.
https://api.linkedin.com/v2/me?projection=(id,profilePicture(displayImage~:playableStreams))
You can see more at the Profile Picture API doc to look at the JSON response or the Profile API doc.
Once the Linkedin user authentication using OAuth 2.x is done, make a request to the people URL.
https://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name,formatted-name,picture-url)?format=json
Where ~ stands for current authenticated user. The response will be something like this ...
{
"id": "KPxRFxLxuX",
"emailAddress": "johndoe#example.com",
"firstName": "John",
"lastName": "Doe",
"formattedName": "John Doe",
"pictureUrl": "https://media.licdn.com/mpr/mprx/0_0QblxThAqcTCt8rrncxxO5JAr...cjSsn6gRQ2b"
}
Hope this helps!
I'm using OWIN in my solution so after the user allows your application to use LinkedIn credentials a simple and plain GET request to URL https://api.linkedin.com/v1/people/~:(picture-URL)?format=json, as explained before with a Bearer authorization in request headers, solved my problems.
My Startup.Auth.cs file
var linkedInOptions = new LinkedInAuthenticationOptions()
{
ClientId = [ClientID],
ClientSecret = [ClientSecret],
Provider = new LinkedInAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
// This is the access token received by your application after user allows use LinkedIn credentials
context.Identity.AddClaim(new Claim(
"urn:linkedin:accesstoken", context.AccessToken));
context.Identity.AddClaim(new Claim(
"urn:linkedin:name", context.Name));
context.Identity.AddClaim(new Claim(
"urn:linkedin:username", context.UserName));
context.Identity.AddClaim(new Claim(
"urn:linkedin:email", context.Email));
context.Identity.AddClaim(new Claim(
"urn:linkedin:id", context.Id));
return Task.FromResult(0);
}
}
};
app.UseLinkedInAuthentication(linkedInOptions);
My method to get the user's profile picture in LinkedIn:
public string GetUserPhotoUrl(string accessToken)
{
string result = string.Empty;
var apiRequestUri = new Uri("https://api.linkedin.com/v1/people/~:(picture-url)?format=json");
using (var webClient = new WebClient())
{
webClient.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + accessToken);
var json = webClient.DownloadString(apiRequestUri);
dynamic x = JsonConvert.DeserializeObject(json);
string userPicture = x.pictureUrl;
result = userPicture;
}
return result;
}
And finally a snippet of my action that consumes the method above:
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
...
var externalIdentity = HttpContext.GetOwinContext().Authentication.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
string accessToken =
externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == "urn:linkedin:accesstoken").Value;
model.PhotoUrl = GetUserPhotoUrl(accessToken);
...
}
I hope it could help.
Best regards
This works well for me!
Explained -
This is for a thumbnail with all other data-
https://api.linkedin.com/v1/people/~:(id,location,picture-urls::(original),specialties,public-profile-url,email-address,formatted-name)?format=json
This is for original image with all other data -
https://api.linkedin.com/v1/people/~:(id,location,picture-url,specialties,public-profile-url,email-address,formatted-name)?format=json
Just use picture-urls::(original)instead of picture-url !
This is currently being used in Gradbee
When you login to linkedin, you will get accesstoken. Use that access token and you can retrieve users data
LinkedInApiClient client = factory.createLinkedInApiClient(accessToken);
com.google.code.linkedinapi.schema.Person person = client.getProfileForCurrentUser(EnumSet.of(
ProfileField.ID, ProfileField.FIRST_NAME, ProfileField.LAST_NAME, ProfileField.HEADLINE,
ProfileField.INDUSTRY, ProfileField.PICTURE_URL, ProfileField.DATE_OF_BIRTH,
ProfileField.LOCATION_NAME, ProfileField.MAIN_ADDRESS, ProfileField.LOCATION_COUNTRY));
String imgageUrl=person.getPictureUrl();
If your goal is simply to display the photo on your site then the LinkedIn Member Profile Plugin may work out for you. It will display the photo, some additional info, along with LinkedIn branding.
Since the LinkedIn API is designed to be used only on behalf of the current logged in user it does not offer similar functionality as the facebook graph api.
This is my solution and it works very very well:
def callback(self):
self.validate_oauth2callback()
oauth_session = self.service.get_auth_session(
data={'code': request.args['code'],
'grant_type': 'authorization_code',
'redirect_uri': self.get_callback_url()},
decoder=jsondecoder
)
me = oauth_session.get('people/~:(id,first-name,last-name,public-profile-url,email-address,picture-url,picture-urls::(original))?format=json&oauth2_access_token='+str(oauth_session.access_token), data={'x-li-format': 'json'}, bearer_auth=False).json()
social_id = me['id']
name = me['firstName']
surname = me['lastName']
email = me['emailAddress']
url = me['publicProfileUrl']
image_small = me.get('pictureUrl', None)
image_large = me.get('pictureUrls', {}).get('values', [])[0]
return social_id, name, surname, email, url, image_small, image_large, me
This may not be quite what you're asking for, but it's useful for individual investigations.
Call up the page in Firefox, left-click the menu over the background image.
Select Inspect Element(Q).
search for -target-image"
That will be the end of of id attribute in an img element.
The src attribute of that img element, will be the URL of the background image.
For me this works
image= auth.extra.raw_info.pictureUrls.values.last.first
with omniauth-linkedin gem