The scenario:
I am building an app that allows the user to sign in using their Google account, it's worth noting that this is done using Firebase authentication.
The problem:
The user signs in perfectly but whenever i get their profile picture it is returned fine but it's very blurry.
I've researched and found some sites mentioning to change the resolution of the Google profile image but I'm not sure if that's possible. I know Facebook has a graph that allows for you to manipulate the URL of the profile image to change the resolution but I'm not sure how to improve the resolution of the profile image via Google.
I've posted a screenshot of the blurry image below:
This is the XML code for the ImageView that I'm loading the profile image in:
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/image_view_profile_pic"
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="36dp"
android:src="#drawable/app_bar_tool_bar_bg"
app:civ_border_width="2dp"
app:civ_border_color="#FFFFFFFF"
android:contentDescription="#string/content_description_profile_picture" />
This is the code I used to get the profile image from Google via Firebase:
private void getUserProfileContent() {
// Check if the user is signed in
if (mUser != null) {
for (UserInfo profile : mUser.getProviderData()) {
// Profile photo url
Uri photoUrl = profile.getPhotoUrl();
// Load user's profile photo from their signed-in provider into the image view
Glide.with(ProfileActivity.this)
.load(photoUrl)
.into(mProfilePic);
}
}
}
This is the code to get the currently authenticated user:
// Variable declaration
private FirebaseUser mUser;
// Initializatioin in onCreate method
mUser = FirebaseAuth.getInstance().getCurrentUser();
Then of course, I call the above method in the onCreate method so it gets executed, like so:
getUserProfileContent();
I have read on this site that Google URLs can be manipulated to change the size of an image:
Details about Google's "magic" URL
Also, I've seen this site mentioning something similar about profile picture being blurry:
Firebase Google Group: Profile picture blurry
As it relates to the second link I haven't quite wrapped my head around how to carry out what they've suggested.
I solved my own problem, I will explain in full detail, see below.
Solution:
This is the newly modified code to my method in the question above, this is the fix:
private void getUserProfileContent() {
// Check if the user is signed in
if (mUser != null) {
for (UserInfo profile : mUser.getProviderData()) {
// Get the profile photo's url
Uri photoUrl = profile.getPhotoUrl();
// Variable holding the original String portion of the url that will be replaced
String originalPieceOfUrl = "s96-c/photo.jpg";
// Variable holding the new String portion of the url that does the replacing, to improve image quality
String newPieceOfUrlToAdd = "s400-c/photo.jpg";
// Check if the Url path is null
if (photoUrl != null) {
// Convert the Url to a String and store into a variable
String photoPath = photoUrl.toString();
// Replace the original part of the Url with the new part
String newString = photoPath.replace(originalPieceOfUrl, newPieceOfUrlToAdd);
// Load user's profile photo from their signed-in provider into the image view (with newly edited Url for resolution improvement)
Glide.with(ProfileActivity.this)
.load(newString)
.into(mProfilePic);
} // End if
} // End if
}
Explanation:
The code is self explanatory but for the sole purpose of clarity for many others who were having issues with this, I basically swapped out the part of the original Url that I retrieved from Google that specified the image's resolution with a higher resolution of my own.
Replaced this "s96-c/photo.jpg" with "s400-c/photo.jpg"
I have provided a screenshot below with TextViews displaying:
Url path of the original Url retrieved from Google (this one has the s96-c in its url)
Url path of the newly modified Url by me (this one has the s400-c in its url)
Original Url retrieved from Google with toString() method called on it. This is the third Url in the screenshot with s96-c
Newly modified Url by me with toString() method called on it. This is the fourth Url (similarly to the 3rd Url in the screenshot this Url has s96-c in its Url String)
In that order
Note:
I wanted to do an in depth explanation with this answer because I wanted to show that even though the string with low res was replaced with high res version, you'll notice the last TextView displays in its Url s96-c and the second-to-last Url (granted you're looking from top to bottom) displays the exact same thing, s96-c
BUT
The resolution indeed improved, so my theory is that even though the resolution improved, by me using a higher value, Google's system returned the improved image with a size of s96-c regardless (Let me know if anyone has a more concrete theory)
Screenshot of profile image with the blurriness fixed (improved resolution):
Anyway there you have it, I wanted to show a screenshot with the Urls and their differences so that I can explain how everything was happening, for anyone who was curious.
I hope this helps many others, because the blurry Google user profile image was a very inconvenient problem for myself.
In my case, inside of the HTML of my Ionic4 component I used:
<img class="avatar" [src]="user.photoURL + '?height=150'">
Adding the height parameter to the end of the URL worked for me.
Easy Fix
Just replace s96-c with s400-c or any other like s300-c
from the image url you get from google.
Example:
Here you can easily see the difference..
Look at the end of url.
https://lh4.googleusercontent.com/-C0Mqxb50Hxg/AAAAAAAAAAI/AAAAAAAADcw/xuG-pk0PzaI/s96-c/photo.jpg
https://lh4.googleusercontent.com/-C0Mqxb50Hxg/AAAAAAAAAAI/AAAAAAAADcw/xuG-pk0PzaI/s400-c/photo.jpg
I feel the code is much clearer this way
private void onSignedInInitialize(FirebaseUser user) {
if(user.getDisplayName() != null && user.getDisplayName().length() > 0)
{
usernameText.setText(user.getDisplayName());
}
String photoUrl;
String provider = user.getProviders().get(0);
if (provider.equals("facebook.com")) {
photoUrl = user.getPhotoUrl() + "?height=500";
}
else if(provider.equals("google.com"))
{
photoUrl = user.getPhotoUrl().toString();
//Remove thumbnail url and replace the original part of the Url with the new part
photoUrl = photoUrl.substring(0, photoUrl.length() - 15) + "s400-c/photo.jpg";
}
else
{
photoUrl = user.getPhotoUrl().toString();
}
Picasso.with(this)
.load(photoUrl)
.placeholder(R.drawable.profile_avatar)
.error(R.drawable.profile_avatar)
.into(circleImageView);
}
Instead of replacing the size, you can also just remove =s96-c from the photoUrl, and you will be receive the max size.
Related
Hi I'm trying to do a simple task of getting the img src url from a website but I can't seem to do it, I've tried various flutter packages and now I've reverted back to vanilla Flutter. This is my code:
onPressed: () async {
http.Response response = await http.get('https://tiktok.com/#$enteredUsername');
dom.Document document = parser.parse(response.body);
final elements = document.getElementsByClassName('jsx-581822467');
print(elements);
},
I'm simply trying to get the image URL from this website (tiktok.com):
I've looked into the source code and it says the class name is 'jsx-581822467', but if I try to use that in the code it returns with a blank list.
How can I just simply get the URL of this profile picture? And the other elements with the 'jsx' prefix as their class names?
I think I figured out what your problem is. The inspector of the web browser displays the HTML on a TikTok profile page. However, this is only generated with JavaScript once the page is loaded. If we download the content via http.get(), we get the raw HTML before JavaScript can do any changes.
Write http.get(), in front of your URL or right-click on the website and click on View Page Source. Now the HTML will be displayed in the same way as your app gets it.
Search for avatar-wrapper round. You won't be able to find it, because the tag from the profile picture doesn't exist here yet.
Fortunately, the URL of the profile picture is already included in other places. Search for <meta property="og:image" content=". You will find only one hit and after the hit the URL of the profile picture starts directly.
Therefore, in my opinion, the easiest way to get the URL is:
download HTML.
remove all text up to <meta property="og:image" content=".
all following characters up to the next " are the URL we are looking for.
Here I have inserted my code, which worked fine for me:
Future<String> getProfileImageUrl(String username) async {
// Download the content of the site
http.Response response = await http.get("https://www.tiktok.com/#$username");
String html = response.body;
// The html contains the following string exactly one time.
// After this specific string the url of the profile picture starts.
String needle = '<meta property="og:image" content="';
int index = html.indexOf(needle);
// The result of indexOf() equals -1 if the needle didn't occurred in the html.
// In that case the received username may be invalid.
if (index == -1)
return null;
// Remove all characters up to the start of the text snippet that we want.
html = html.substring(html.indexOf(needle) + needle.length);
// return all chars until the first occurrence of '"'
return html.substring(0, html.indexOf('"'));
}
I hope that I could help you with my explanation.
Edit 1: General approach
view page source to view HTML of the page
search for the desired substring.
Select the previous 10 to 15 characters and see how often this string occurs before.
If it occurs more than once, you must call html = html.substring(html.indexOf(needle) + needle.length); accordingly often repeatedly.
reload the page and check if it still works.
now you have found your needle string.
Here is my code to display profile picture using gravatar.
ParseUser user = mUsers.get(position);
String email = user.getEmail().toLowerCase();
if (email.equals("")) {
holder.userImageView.setImageResource(R.drawable.avatar_empty);
} else {
String hash = MD5Util.md5Hex(email);
String gravatarUrl = "http://www.gravatar.com/avatar/" + hash + "?s=204&d=404";
Picasso.with(mContext).load(gravatarUrl)
.placeholder(R.drawable.avatar_empty)
.into(holder.userImageView);
}
But it is not showing even my profile picture and loads empty drawable.
You used a bunch of fake emails to populate your friend list, if so, gravatar won't be able to find images for those fake emails. So gravatar will return a 404, and your code will use the default "avatar_empty" image in the drawable folder.
A quick way to test to see if gravatar is working is to change the &d=404 to &d=monsterid and create a friend with a fake email "SDFSDSF#DSFSsdfsFSFSssf.com"
That friend will have an gravatar cartoon image.
Also you can try put http://www.gravatar.com/avatar/edb1260aa6f7f77688deee83e0a088f7?s=204&d=monsterid in your gravatarUrl. It will show picture.
Hope this helps someone , this is the code i used.
get library from:- https://github.com/tkeunebr/gravatar-android (you will get the .jar,, add it to lib)
Code for loading gravatar:
String gravatarUrl = Gravatar.init().with(user.email).size(100).build();
Picasso.with(mContext)
.load(gravatarUrl)
.into((ImageView) convertView.findViewById(R.id.user_avatar));
And if you want to set a default image in case of there is no gravatar set for the email(to override the default gravatar) then use:
String gravatarUrl = Gravatar.init().with(user.email).defaultImage(defaultImageUrl).size(100).build();
Hope this helps someone.
I'm currently getting the newsfeed of a Facebook user. Currently, I can only retrieve thumbnail images that are associated with links, rather than the full-size image. Does anyone know how to get a larger image?
I've looked at the following posts and tried their solutions; however, the posts seem outdated and the facebook graph api seems to have changed since then:
Facebook Graph API Change: Picture type (size) no longer working?
Facebook API post: How to get larger thumbnail?
Please note that I'm on the me/home edge, so the answer below returns an error. See comments below.
my code is:
params.putString("fields","id,actions,application,caption,created_time,description,from,link,message,message_tags,"
+ "name,object_id,picture,place,source,status_type,story,updated_time,type,status_type,story,to,type,"
+ "updated_time,with_tags");
Change to this:
params.putString("fields","id,actions,application,caption,created_time,description,from,link,message,message_tags,"
+ "name,object_id,full_picture,place,source,status_type,story,updated_time,type,status_type,story,to,type,"
+ "updated_time,with_tags");
Here picture.height(1000) will give you a large image. and you can put your own required size but it is not supported in me/home i have searched a lot.
For Testing purposre use this link :Facebook graph explorer.
Eventually I came to this solution:
1) find the URL of the larger image (see code below)
2) get bitmap from URL and add to application UI.
The code mentioned above:
private String getRealURL(String smallURL){
if (smallURL.contains("url=http")){
String[] pieces = smallURL.split("url=");
pieces[1].replace("%2F", "//");
pieces[1].replace("%3A", ":");
Log.e("RealURL1:", pieces[1]);
return pieces[1];
}
else{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.setLength(0);
stringBuilder.append("https://graph.facebook.com/");
stringBuilder.append(item.getObjectID());
stringBuilder.append("/picture?type=normal&access_token=");
stringBuilder.append(Session.getActiveSession().getAccessToken());
Log.e("RealURL2:", stringBuilder.toString());
return stringBuilder.toString();
}
}
Simply use this field ?field=full_picture instead of picture.
?field=full_picture is the only way to get it to work now. I have been searching everywhere, and finally found the answer here. picture field doesn't support subfields any more so you can't use picture.width.height any more
It's weird, but till yesterday i was able to get the gplus user's image in my app but today it's just not coming. Nothing simply blank. And just appears at some time..
I have been using the urls specified in Getting Google+ profile picture url with user_id but these all seem invalid and gives 404 Error.
https://plus.google.com/s2/photos/profile/116018066779980863044?sz=100
If anybody could help me out why this weird behaviour. The Profile pic appears seldom. But mostly it's blank.
The image URL you were using was never a public API and so there was no guarantee it would continue to work. The recommended practice going forward is to use the people.get API method to get the profile => image => url value instead. That URL could stop working if the user changes their avatar so you might want to fetch the actual image and cache it on your own servers.
I think the Image url has been updated.
Inorder to get that, we can use the PlusClient objects methods:
imageURL = mPlusClient.getCurrentPerson().getImage().getUrl()
{Returns a String - Image Url as String}
imageURL = mPlusClient.getCurrentPerson().getImage()
{Returns an instance of Image object}
I used graph API Json Response of Facebook Wall Post Images and display in my APP i successfully got it. But the wall images look very Blur how to resolve? i used this code for get wall picture
URL url=new URL(hashMap.get("picture_url"));
bitmap=BitmapFactory.decodeStream(url.openConnection().getInputStream());
((ImageView)view.findViewById(R.id.imageView_FullImage)).setImageBitmap(bitmap)
The Facebook Graph API as well as the FQL data set always returns the Picture URL of a thumbnail. If you look at the URL it returns, it will have one of these ending (right before the image extension .jpg, .png, etc) _t., _a.. For example, if the URL is to a JPG file, it could have an ending _t.jpg
The idea is to swap the ending and choose a normal size for the image that is returned. To do this, use the code below that will replace the endings with the one for normal sized images (that should have the _n.)
By the way, I don't think the tag you are looking for is picture_url. It should be just picture. But regardless, get the source URL as shown below, replace the endings and then pass it to the this line in your code:
// THIS SHOULD BE AFTER THE if....else code block
bitmap=BitmapFactory.decodeStream(url.openConnection().getInputStream());
CODE TO REPLACE THE VARIOUS THUMBNAIL IMAGES: By the way, this is production code and works perfect.
String PICTURE_URL;
String getPicture = JOFeeds.getString("picture");
if (getPicture.contains("_t.")) {
PICTURE_URL = getPicture.replaceAll("_t.", "_n.");
} else if (getPicture.contains("_a.")) {
PICTURE_URL = getPicture.replaceAll("_a.", "_n.");
} else if (getPicture.contains("_s.")) {
PICTURE_URL = getPicture.replaceAll("_s.", "_n.");
} else if (getPicture.contains("_q.")) {
PICTURE_URL = getPicture.replaceAll("_q.", "_n.");
}
Note: However, in some cases, like a Video preview or a Link preview, it will not always have a bigger image available. Nothing much you can do about it nor can Facebook I suspect. These typically come from posts that are shared by users from other websites.