How to use cursor-based pagination with Android Facebook API - java

I am trying to retrieve items from my Facebook news feed using the graph API. The code (unfinished) I am using is below, which seems to only be returning a single news feed post. I have read the documentation on cursor based pagination but it does not explain how to implement it, nor have i found any other resources explaining this matter.
// Get items from users news feed
public void getFeed() {
Session s = Session.getActiveSession();
new Request(
s,
"/me/home",
null,
HttpMethod.GET,
new Request.Callback() {
public void onCompleted(Response response) {
/* handle the result */
JSONArray json = null;
JSONObject current = null;
try {
json = (JSONArray)response.getGraphObject().getProperty("data");
} catch(Exception e) {
// TODO
}
for(int i=0; i<5; i++) {
try {
current = json.getJSONObject(i);
Log.d("Value: ", current.get("message").toString());
} catch(Exception e) {
// Nothing
}
}
}
}
).executeAsync();
}
As I am still experimenting, I am just trying to pull down 5 news feed items and output the message JSON attribute. Could anybody advise me on how to properly implement the cursor based pagination to pull down an arbitrary number of feed posts at a time? Thanks

The person in your link is using FB-Andriod-SDK 3.0.1
Source
Which means it is using Graph v1.0
FB-Andriod-SDK 3.8 and above started using Graph v2.0
In Graph v2.0 and above the ability to use the "read_stream" permission became severely limited. So much so that unless you are a Facebook engineer you won't get it.
Limited Use
This permission is granted to apps building a Facebook-branded client on platforms where Facebook is not already available. For example, Android and iOS apps will not be approved for this permission. In addition, Web, Desktop, in-car and TV apps will not be granted this permission.
Source, Scroll down to "read_stream"
The user/home edge requires "read_stream" (user is a place holder for a User ID or "Me" keyword)
Permissions
A user access token with read_stream permission is required to view that person's news feed.
Source
This also extents to user/feed edge
Permissions
Any valid access token is required to view public links.
A user access token with read_stream permission is required.
Only posts whose authors have also granted read_stream permission to the app will be shown.
Source
As well as user/posts edge
This is a duplicate of the /feed edge which only shows posts published by the person themselves.
Source
On April 30, 2015 Graph v1.0 will be completely gone.
The current, latest version of the Graph API is v2.2. Apps calling v1.0 have until April 30, 2015 to upgrade to v2.0 or later.
Source, under "Staying up to date"
More insightful information about this can be found here.
Read all the comments Emil (FB Engineer) and Simon (Graph Product Manger) are the best sources
So what it boils down to is. You are attempting to do something that the Facebook developed app already does and they don't want you to do it.

First of all you can not use "me/home" as a call. It requires the "read_stream" permission and you'll never get that approved.
There is really no way to get this data on your own. You'll have to use one of FB's Media Partners
Here is more info.
Click here for more info

Related

Google Maps Elevation API android studio

I am creating an android app to record a user's activity using Google Maps SDK and the Google Play Services Location API. I am attempting to retrieve the user's elevation based on a given latitude and longitude. I originally used Location#getAltitude() but then realised that does not give the elevation above sea level.
I proceeded to use the open elevation API using the following query string:
String url = "https://api.open-elevation.com/api/v1/lookup?locations=" + latLng.latitude + "," + latLng.longitude;
However, that API appears to be much too slow in generating a response. I then found the Google Maps Elevation API which we can make a request using a URL also. However, we need to pass an API key and I do not want to pass this API key in the URL string and end up committing it to the remote repository.
In this repo (https://github.com/googlemaps/google-maps-services-java) I found the class:
/src/main/java/com/google/maps/ElevationApi.java which I thought I could use to avoid messing around with http requests.
In my gradle, I included this dependency:
implementation 'com.google.maps:google-maps-services:0.18.0'
At the moment, the code to retrieve the elevation is as follows:
ElevationApi.getByPoint(new GeoApiContext.Builder().apiKey(API_KEY).build(), latLng)
.setCallback(new PendingResult.Callback<ElevationResult>() {
#Override
public void onResult(ElevationResult result) {
consumer.doAction(result.elevation);
}
#Override
public void onFailure(Throwable e) {
e.printStackTrace();
}
});
What do I pass in for API_KEY here since I don't want to commit it to the repository? I have an api key defined in local.properties for maps, however, like so:
MAPS_API_KEY=<API_KEY_HERE>
Basically, my question is, can I define an API key in a properties file that is not committed to GitHub and then reference it in the code?
Thanks for any help.
Update:
I have managed to read the API key from local.properties using gradle but got an exception from the ElevationApi saying API 21+ expected, but was 30...strange. So I went back to the open-elevation API with the following Volley request:
/**
* Calculates elevation gain for the provided recording service
* #param recordingService the recording service to calculate elevation gain for
* #param response the handler to consume the elevation gain with
*/
public static void calculateElevationGain(RecordingService recordingService, ActionHandlerConsumer<Double> response) {
ArrayList<Location> locations = recordingService.getLocations();
JSONArray array = constructLocations(locations);
try {
if (array != null) {
RequestQueue requestQueue = Volley.newRequestQueue(recordingService);
String url = "https://api.open-elevation.com/api/v1/lookup";
JSONObject requestHeader = new JSONObject(); // TODO this seems very slow
requestHeader.put("locations", array);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, requestHeader,
response1 -> handleSuccessfulResponse(response1, response), RecordingUtils::handleErrorResponse);
request.setRetryPolicy(new DefaultRetryPolicy(500000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(request);
}
} catch (JSONException ex) {
ex.printStackTrace();
}
}
I had to set the timeout to a high number not sure how hight it should be because I was getting Volley timeout errors due to the slow response times.
Are there any other ways I can retrieve elevation about sea level?
Yeah, open-elevation.com has intermittent issues with timeouts and latency.
There are some alternatives listed on this GIS stack exchange question Seeking alternative to Google Maps Elevation API. I'm the developer of Open Topo Data which is the most-voted answer over there. You can host your own server with docker, and I also have a free public API which has pretty good latency and uptime.
There's also GPXZ as an alternative to the Google Elevation API with higher-quality data, but it requires an API key so would have the same issue as with Google Maps.
I advise a different direction: stay with the Google and the API key, but employ best practices regarding secrets and source repositories. Since you are dealing with an Android app and not a webapp your key can be somewhat safe inside your app binary (versus a key in a web deployed app is exposed).
Bets practices:
Do not commit the API key. The best to achieve this is to exclude the file which contains the key from the source control repo. That can simply be done with .gitignore. For example this Codelab has a file with the secret, but it has a dummy value and normally this file should be excluded from the source. It is only there because that is an educational code lab.
As a security measure take advantage of GitGuardian to scan your repos in case you'd accidentally push an API key. In such events you'd get a notification. As for me I forked that Geospatial API codelab and saw the key file was in the gitignore and I accidentally pushed a key.
In case you accidentally push a key in a commit it's not enough to reverse the commit and delete the file! Scavenger bots will still find the information in your git history. Rather immediately disable the key and generate another one.
If you are dealing with a webapp you can restrict the API key usage to your webapp's domain. Similarly you can restrict the key to specific Android app signatures (don't forget to add your developer environment's signature) too. This guarantees that even if someone steals the key they probably won't be able to use it.

How To Charge Card In Stripe Using Java(Android)

After searching lot's of asked questions regarding the charging the card using stripe. Most of the question are not answer yet and not able to find the way to charge the payment.
Here what i did in my project:
I am able to successfully got the token from stripe server.
try {
carToSave = mCardInputWidget.getCard();
Log.d(TAG, carToSave.toString());
if (carToSave == null) {
Toast.makeText(this, "Please fill information", Toast.LENGTH_SHORT).show();
} else {
//get key from https://dashboard.stripe.com/account/apikeys
Stripe stripe = new Stripe(StripeActivity.this, "put key here");
stripe.createToken(carToSave, new TokenCallback() {
#Override
public void onError(Exception error) {
// Show localized error message
Log.d(TAG, "onError");
}
#Override
public void onSuccess(Token token) {
//do charge with token
Log.d(TAG, token.getId());//token
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
I have spend lot's of hours on Creating Charges Official docs and in the official docs they were using Charge class to charge the card but this class is not included in latest docs.
Here are the link of previously asked question on stack-overflow but not contain any relevant answer that's why i am posting this answer.
Link 1
Link 2
3.I have followed the Official Stripe Github but left with empty hand.
Note: Most of docs are using Charge class but that class not included in latest sdk of stripe.
I also had the same issue, so I had a look at this post.
The Charge class and, Stripe.api key all available in its Java SDK.
implementation 'com.stripe:stripe-java:5.36.0'
You should never create a charge from within your Android mobile app. In order to create a charge, you need to use your secret API key. Your secret API should never ever be kept in a mobile application because someone could retrieve this key and they would be able to create charges and refunds on your Stripe account.
You can create charges in your server-side code like in this Stripe example backend:
https://github.com/stripe/example-ios-backend/blob/0adc94abc7e2e78464e027e510da3d99152b13e6/web.rb#L34
The same issue for me. The problem for me started today in the demo account after having managed to take the process to the end. This leads me to conclude that either is some stripe problem. The process of obtaining the token is as simple as that shown in the Suraj Bahadur code. In the Stripe dashboard, the token request is immediately indicated, but the token does not reach the device that requested it.
plz follow this I got it from stripe payment doc, here is the link :https://stripe.com/docs/charges
after getting the token from stripe server use as request param.
you use the String token = request.getParameter("token")

Java Read Facebook Wall

I'm building a web portal by using Java; besides other requirements, I'm struggling my mind one one very simple (at least at first view) requirement:
my customer wants on his portal the first N posts of his facebook wall
and he wants to read the first N tweets of his twitter page
Since my java code is based on Spring, I wanted to use spring social, spring social twitter and spring social facebook in order to satisfy the requirement
With twitter I had no problem; in fact I
created an app on twitter
got twitter app id and app secret
prepared code
In a couple of hours, all worked pretty good
Problems were born with facebook and it's a lot of time I'm fighting with it
I passed from spring social to facebook4j (since this last one seems to me stronger).
I did the following
created an app on FB
got the facebook appId and appSecret
told to the code that I need the read_stream permission
prepared the code
But I'm not able in reading posts from my wall
Is there anyone who was able in satisfying this kind of scenario?
here my facebook4j code
private static final Logger log = LoggerFactory.getLogger(FacebookTest.class.getName());
public static void main (String[] a)
{
try
{
ConfigurationBuilder cfgBui = new ConfigurationBuilder();
cfgBui.setDebugEnabled(true);
cfgBui.setOAuthAppId(myAppId);
cfgBui.setOAuthAppSecret(myAppSecret);
cfgBui.setUseSSL(true);
Configuration cfg = cfgBui.build();
FacebookFactory ff = new FacebookFactory(cfg);
OAuthSupport support = new OAuthAuthorization(cfg);
support.setOAuthPermissions("read_stream");
AccessToken appAccessToken = support.getOAuthAppAccessToken();
Facebook face = ff.getInstance(appAccessToken );
ResponseList<Post> posts = face.searchPosts("test");
for (Post post : posts)
{
System.out.println(post.getId());
}
} catch (Exception e)
{
log.error("Errore", e);
}
}
As far as I understood, I should need the user access token, but I don't know how to generate it; should I create a login flow and show to the user the FB login dialog? If so, why should I create app id and app secret? They have no sense in my scenario
Moreover...in my case...the server side should authenticate on FB and read posts from a well know user wall (the wall of my customer...) so....where should I present the login dialog? where should I redirect after the FB login?
Is there any good man :) who can clarify to me the FB read post flow?
You MUST use one of the possibilities to authorize the user (with read_stream) in order to get access to his stream. Here´s the link to all the possibilities: https://developers.facebook.com/docs/facebook-login/v2.2
You can also generate Access Tokens with the Graph API Explorer: https://developers.facebook.com/tools/explorer/
Detailed information about Access Tokens and how to generate them can be found in the following links:
https://developers.facebook.com/docs/facebook-login/access-tokens
http://www.devils-heaven.com/facebook-access-tokens/
Keep in mind that an Extended User Token only lasts for 60 days, after that your customer would have to refresh it manually. In general, you are not allowed to use User Profiles for commercial reasons, and it´s very unusual to show a User stream on a website.
Better: Use a Facebook Page. /page-id/feed with an Extended Page Token that lasts forever.
If you use spring-social-facebook, you could let the user login via (front-end login flow) and then you can access the users wall. However, user would need to login and authorize your app to perform the operations.
Here is a spring social sample project that demo's how spring-social-facebook login is done https://github.com/spring-projects/spring-social-samples
Also, within your java code you can use feedoperations to gather information about home feed and also query against it. Checkout the documentation.
facebook.feedOperations().

How to get unread messages using Graph API?

I am developing an app that gets Facebook unread inbox message .
The following v2.0 FQL query works fine:
SELECT sender, body FROM unified_message
WHERE thread_id IN
(SELECT thread_id FROM unified_thread WHERE folder = 'inbox' AND unread=1)
AND unread=1
ORDER BY timestamp DESC
As a result, we have a list of all unread messages.
But, Facebook says:
Version 2.0 of the Facebook Platform API is the last version where FQL
will be available. Versions after 2.0 will not support FQL. Please
migrate your applications to use Graph API instead of FQL. Please see
our changelog for current version information.
So, I am looking for a way to do that with Graph API only. I tried the following:
Bundle params = new Bundle();
params.putString("unread", ">0");
new Request(session,"/me/inbox/",params,HttpMethod.GET,new Request.Callback() {
public void onCompleted(Response response) {
...
}
}
).executeAsync();
without success. I get all the threads whereas I only need the unread threads. How to do that then?
I am sorry for the advice I gave when I blindly quoted the following Facebook notice:
However, you should not use FQL anymore:
Version 2.0 of the Facebook Platform API is the last version where FQL will be available. Versions after 2.0 will not support FQL. Please
migrate your applications to use Graph API instead of FQL. Please see
our changelog for current version information.
This statement is true, but to follow it isn't very smart.
Indeed, I checked further and found out:
v2.0 is available until August 7th 2016,
the Graph API is not yet suitable for your current usage.
I didn't expect the Graph API to be so weak. The Graph API makes it impossible to build a request by filtering any field. For example, we can't do simple things such as:
me/threads?unread_count>0,
me/threads?fields=unread_count.more(0).
Right now with Graph, you would have to iterate through all the threads and check which one have unread > 0. You would lose time and bandwidth. Moreover, the message table doesn't even have an unread field which would make it impossible for you to find any specific unread message(s).
So, the best is to keep using FQL. You are safe for now. By 2016, Facebook will probably have improved the way we query with Graph API.
Wait and see...

How to configure a Two-legged Spring-OAuth provider/client?

Im working on oauth 1 Sparklr and Tonr sample apps and I'm trying to create a two-legged call. Hipoteticly the only thing you're supposed to do is change the Consumer Details Service from (Im ommiting the igoogle consumer info to simplify):
<oauth:consumer-details-service id="consumerDetails">
<oauth:consumer name="Tonr.com" key="tonr-consumer-key" secret="SHHHHH!!!!!!!!!!"
resourceName="Your Photos" resourceDescription="Your photos that you have uploaded to sparklr.com."/>
</oauth:consumer-details-service>
to:
<oauth:consumer-details-service id="consumerDetails">
<oauth:consumer name="Tonr.com" key="tonr-consumer-key" secret="SHHHHH!!!!!!!!!!"
resourceName="Your Photos" resourceDescription="Your photos that you have uploaded to sparklr.com."
requiredToObtainAuthenticatedToken="false" authorities="ROLE_CONSUMER"/>
</oauth:consumer-details-service>
That's adding requiredToObtainAuthenticatedToken and authorities which will cause the consumer to be trusted and therefore all the validation process is skipped.
However I still get the login and confirmation screen from the Sparklr app. The current state of the official documentation is pretty precarious considering that the project is being absorbed by Spring so its filled up with broken links and ambiguous instructions. As far as I've understood, no changes are required on the client code so I'm basically running out of ideas. I have found people actually claiming that Spring-Oauth clients doesn't support 2-legged access (which I found hard to believe)
The only way I have found to do it was by creating my own ConsumerSupport:
private OAuthConsumerSupport createConsumerSupport() {
CoreOAuthConsumerSupport consumerSupport = new CoreOAuthConsumerSupport();
consumerSupport.setStreamHandlerFactory(new DefaultOAuthURLStreamHandlerFactory());
consumerSupport.setProtectedResourceDetailsService(new ProtectedResourceDetailsService() {
public ProtectedResourceDetails loadProtectedResourceDetailsById(
String id) throws IllegalArgumentException {
SignatureSecret secret = new SharedConsumerSecret(
CONSUMER_SECRET);
BaseProtectedResourceDetails result = new BaseProtectedResourceDetails();
result.setConsumerKey(CONSUMER_KEY);
result.setSharedSecret(secret);
result.setSignatureMethod(SIGNATURE_METHOD);
result.setUse10a(true);
result.setRequestTokenURL(SERVER_URL_OAUTH_REQUEST);
result.setAccessTokenURL(SERVER_URL_OAUTH_ACCESS);
return result;
}
});
return consumerSupport;
}
and then reading the protected resource:
consumerSupport.readProtectedResource(url, accessToken, "GET");
Has someone actually managed to make this work without boiler-plate code?

Categories