Getting Profile Photo from Microsoft Graph API for Android - api

I have recently started working on an android project that uses Microsft authentication and graph API. By following this:
https://learn.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-android
I am able to authenticate and get some data from graph API. Now I want to load the profile photo of Microsoft account in the app. For this purpose, I used ProfilePhoto object with a call back as follows:
graphClient
.me()
.photo()
.buildRequest()
.get(new ICallback<ProfilePhoto>() {
#Override
public void success(ProfilePhoto profilePhoto) {
Log.d(TAG, "Found " + profilePhoto.getRawObject().toString());
}
#Override
public void failure(ClientException ex) {
displayError(ex);
}
});
Here profilePhoto.getRawObject() returns a json file like:
{"#odata.context":"https://graph.microsoft.com/v1.0/$metadata#users('hanzla_hawk%40outlook.com')/photo/$entity","#odata.mediaContentType":"image/png","#odata.mediaEtag":"W/\"8050a078da935403cf67163f23f1baace5c7abf3ff784452cb08c38660308a83\"","id":"default","height":256,"width":256}
With this Json, how can I load the image into an image view? I have previous experience with Picasso and other fake apis. But right now I just dont know what should I pass in the Picasso to load image from this json.

I have just make a call to get a profile photo to show on an Android app using Jetpack Compose views in Kotlin. To achieve it I have followed your question and this tutorial:
https://learn.microsoft.com/en-us/graph/tutorials/android
You almost got it. Just add .content() call between .me().photo() and .buildRequest().
This is my code on my project to get the photo content:
// GET /me/photo/$value (logged in user)
fun getUserPhoto(
onGotPhoto: (ImageBitmap) -> Unit,
onGotError: (Exception) -> Unit
) {
mClient!!.me().photo().content().buildRequest()
.async
.thenAccept { inputStream ->
val bitmap = BitmapFactory.decodeStream(inputStream).asImageBitmap()
onGotPhoto.invoke(bitmap)
}
.exceptionally { processError(it, onGotError) }
}

Related

Getting large profile picture from Facebook Graph-API

I am building a Kotlin app and am using FirebaseAuth for login. I activated Facebook login via Firebase and it works fine. My problem is that the created Firebase user's photoUrl: (https://graph.facebook.com/<UserId>/picture) is pointing to a tiny version of it's Facebook profile picture, instead of a normal sized one.
I found this solution: https://stackoverflow.com/a/52099896/13674106. The Google part of this answer worked perfectly for me, but in the Facebook case I am now getting a default avatar image (in the right resolution). My code looks like this:
fun handleSignInSucceeded(dataIntent: Intent?) {
val response = IdpResponse.fromResultIntent(dataIntent)
// For new created users, check if a photo is available from the auth provider
if (response?.isNewUser == true) {
// All users have a default FirebaseAuth provider data - we want to check which is the
// other one
currentUser.value?.providerData
?.find { it.providerId != FirebaseAuthProvider.PROVIDER_ID }?.apply {
val photoUrl = when (providerId) {
GoogleAuthProvider.PROVIDER_ID ->
photoUrl.toString().replace("s96-c", "s400-c").toUri()
FacebookAuthProvider.PROVIDER_ID ->
photoUrl.toString().plus("?type=large").toUri()
else -> null
}
photoUrl?.let { updatePhotoUri(it, false) }
}
}
}
fun updatePhotoUri(photoUrl: Uri, uploadToStorage: Boolean = true): Task<Void>? {
val profileUpdates = UserProfileChangeRequest.Builder()
return if (uploadToStorage) ...
else updateProfile(profileUpdates.setPhotoUri(photoUrl).build())
}
private fun updateProfile(profileUpdates: UserProfileChangeRequest): Task<Void>? {
return currentUser.value?.updateProfile(profileUpdates)
?.addOnCompleteListener {
if (it.isSuccessful) {
Log.d(TAG, "User profile updated.")
_currentUser.value = firebaseAuth.currentUser
}
}
}
Where _currentUser is a private MutableLiveData<FirebaseUser?> shadowed by a public LiveData<FirebaseUser?> called user which is binded to my ImageView on the fragment:
<ImageView
android:id="#+id/image_profile_picture"
...
app:userPhotoSrc="#{profileViewModel.user}" />
Where userPhotoSrc is implemented by the following BindingAdapter using Glide:
#BindingAdapter("userPhotoSrc")
fun ImageView.setUserPhotoSrc(user: FirebaseUser?) {
Glide.with(context)
.load(user?.photoUrl)
.circleCrop()
.fallback(R.drawable.ic_profile_black_24)
.into(this)
}
I checked in debug and the value of user?.photoUrl at that point is https://graph.facebook.com/<UserId>/picture?type=large as expected.
I found this thread: Retrieving Default Image All Url Profile Picture from Facebook Graph API, Which shows a problem similar to mine, but according to the answers there, my code should work by now. I also tried to use the height parameter instead of type, like stated in this answer: https://stackoverflow.com/a/50710161/13674106, But I got the same result.
Please help me solve it,
Omer

How to make chloropleth using Mapbox for Andriod, where the data comes in a GEOJSON

After getting a GEOJSON file which has all the boundaries of each country. From: https://datahub.io/core/geo-countries#data
How does one make a chloropleth using Mapbox, for a Andriod application being built using Kotlin.
private fun drawBoundaries(){
mapboxMap.getStyle {
try {
val source = GeoJsonSource("geojson-source", URI("assets://countries.geojson"))
it.addSource(source)
} catch (exception: URISyntaxException) {
Log.d(TAG, exception.toString())
}
}
}
And I am guessing fill is as follows in the link: https://docs.mapbox.com/android/maps/overview/data-driven-styling/#fill
mapboxMap.getStyle {
val fillLayer = FillLayer("layer-id", "source-id")
fillLayer.setProperties(PropertyFactory.fillColor(Color.GREEN))
it.addLayer(fillLayer)
}
Yes, FillLayer will be used and then you'll need to style it based on your data.
See https://docs.mapbox.com/android/maps/examples/join-local-json-data-with-vector-tile-geometries and https://docs.mapbox.com/android/maps/examples/update-by-zoom-level
Edit: Hm, looks like a video's missing for https://docs.mapbox.com/android/maps/examples/join-local-json-data-with-vector-tile-geometries.
https://imgur.com/a/THn7EoO shows what the example looks like.

How to handle send intent (share menu item) in react native app?

I have successfully configured iOS app to handle audio document types (not deeplinks!) so I can use share dialog to open audio files in my app, this works fine.
I have successfully configured Android intent-filter in the AndroidManifest.xml to hande audiofiles same way, this is also recognized fine by Android system and I see my app when I use share menu on audiofiles. However, Android implementation of Linking component seems to ignore SEND intent actions and only care about View intent actions as I saw on IntentModule.java:55:
if (Intent.ACTION_VIEW.equals(action) && uri != null) {
initialURL = uri.toString();
}
I tried to patch intent in my MainActivity.java to make it return same uri with VIEW action, but this always produces an error in runtime.
#Override
public Intent getIntent() {
Intent origIntent = super.getIntent();
if (origIntent != null && Intent.ACTION_SEND.equals(origIntent.getAction())) {
return new Intent(Intent.ACTION_VIEW, origIntent.getData());
}
return origIntent;
}
However I always get an error indicating that getData is null.
I saw this answer, but having a share extension is an overkill for me.
I discovered that Intent might contain additional information called ClipData, which can contain Uri as well. My luck was that I had exactly one Uri (I guess it can contain multiple Uri objects if I share multiple audiofiles at once. So this code worked, I can now share files to react native app
#Override
public Intent getIntent() {
Intent origIntent = super.getIntent();
if (origIntent != null && Intent.ACTION_SEND.equals(origIntent.getAction())) {
return new Intent(Intent.ACTION_VIEW, this.uriFromClipData(origIntent.getClipData()));
}
return origIntent;
}
private Uri uriFromClipData(ClipData clip) {
if (clip != null && clip.getItemCount() > 0) {
return clip.getItemAt(0).getUri();
}
return null;
}

Populate AtlasConversationsRecyclerView with custom HTTP response

I am working on an Android app, using Layer Atlas for the conversations section. Right now I am trying to populate the conversations list (AtlasConversationsRecyclerView) with my own query:
private AtlasConversationsRecyclerView mConversationsList;
.
.
.
HTTPRequestManager.fetchConversations(
new HTTPRequestManager.VolleyCallback() {
#Override
public void onSuccess(String response) {
JSONArray jsonArray = Base.toJSONResponse(response);
JSONArray sortedJsonArray = Base.sortJSONArray(jsonArray, Base.CREATE_TIMESTAMP);
// mConversationsAdapter.setData(sortedJsonArray);
}
}, Base.mChannelId);
What I normally do to populate an ordinary RecyclerView is write an adapter for it, specifically a setData() method that solves the query-view integration (mConversationsAdapter.setData(..)). This time, I have the query response, but I don't understand how to use it to populate the AtlasConversationsRecyclerView, which has its own adapter.
The code that comes next:
// Atlas methods
mConversationsList.init(getLayerClient(), getPicasso())
.setInitialHistoricMessagesToFetch(20)
.setOnConversationClickListener(new AtlasConversationsAdapter.OnConversationClickListener() {...}
This is what I found on the reference files, but I am missing the query-adapter integration part.
Could you please give me some advice?
Thank you,
Michelle

Wicket Deployment mode map resources wrong way

I have Page
getRootRequestMapperAsCompound().add(new NoVersionMapper("/card/${cardId}", CardPage.class));.
On this page there is TinyMCE4 editor. Which try to load images using relative path "images/1.jpg"
I've added resource mapping to allow images successfuly loaded.
mountResource("/card/image/${imageId}", imageResourceReference);
In DEVELOPMENT mode everything work nice, image are loaded in to editor, but in DEPLOYMENT mode, Page has been called twice, first time for /card/1 and second time for /card/image/1.jpg.
How to correctly mount resources for DEPLOYMENT mode?
UPDATE look like found the reason
public int getCompatibilityScore(Request request)
{
return 0; // pages always have priority over resources
}
, but then the question is: "Why it is working nice in development mode"?
Update 2 I haven't find better solution then add my own Resource Mapper with overrided getCompatibilityScore()
public class ImageResourceMapper extends ResourceMapper {
private String[] mountSegments;
public ImageResourceMapper(String path, ResourceReference resourceReference) {
super(path, resourceReference);
mountSegments = getMountSegments(path);
}
public ImageResourceMapper(String path, ResourceReference resourceReference, IPageParametersEncoder encoder) {
super(path, resourceReference, encoder);
mountSegments = getMountSegments(path);
}
#Override
public int getCompatibilityScore(Request request) {
if (urlStartsWith(request.getUrl(), mountSegments)) {
return 10;
}
return 0;
}
}