Android - Facebook Graph API - not able to get AccessToken - android

So I'm trying to fetch Data from a Facebook page and in the Graph Explorer I'm doing just fine. I am using a global app Token.
I am able to fetch data here. So now I'm trying to do following:
GraphRequest request = GraphRequest.newGraphPathRequest(
accessToken,
"/<-pageid->/posts",
new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
// Insert your code here
}
});
request.executeAsync();
}
But i just don't know how to create the Access Token as java Object.
AccessToken.getCurrentAccessToken();
is returning null in my case. I called following code in the beginning:
FacebookSdk.sdkInitialize(getApplicationContext());
AppEventsLogger.activateApp(this);
And did everything in the API Quickstart guide.
I tried to initialize a new Object of AccessToken, but I'm missing so many parameters and filling null didn't work out well. I just have an AppToken as String fetched as json from the graph api and a UserToken. How to achieve getting the AccessToken?

I got it working with a little workaround for everyone reading the question:
I didn't use the Facebook Android SDK, I just sent an GET-Request via my android app to fetch the json data and get it into my controller. I used following code:
public class FacebookController {
public static JSONObject readJsonFromUrl() throws IOException, JSONException {
InputStream is = new URL("https://graph.facebook.com/<page_id>/posts?limit=100&access_token=<my-access-token>").openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
Do not forget to wrap it in an AsyncTask when using it.

Related

How to send a json to asp.net api Controller from android studio app?

I wrote an app where a user has to fill some text fields with infomation
like name, age ... When he clicks a button the data is being send to my api controller where the put methode saves the data in a data base.
This is kind of working exept that I don´t know how to send a json to my controller.(I researched several days but nothing worked)
So what I do at the moment is that I write an url conform string with my data
so that in my controller I read out of the string what I need to know.
This is a very bad solution!(I can´t do spaces or slashes and so on...)
To send my UserData I hava build an AsyncTask (When I didn´t I got an Exeption)
class SendUserTask extends AsyncTask<String, Void, String>{
public AsyncResponse delegate = null;
User user;
#TargetApi(Build.VERSION_CODES.KITKAT)
protected String doInBackground(String... urls) {
try {
String r = sendUser("name" + user.getName() + "street" + user.getStreet());
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public void setUser(User u){user = u;}
public static String sendUser(String userData) throws Exception {
URL url = new URL("http://my-address:port/api/users/"+ userData);
HttpURLConnection c =(HttpURLConnection) url.openConnection();
c.setRequestMethod("PUT");
BufferedReader in = new BufferedReader(new InputStreamReader(
c.getInputStream()));
String inputLine;
String result = "";
while ((inputLine = in.readLine()) != null)
result = inputLine;
in.close();
return result;
}
}
this methode works fine when I just want to send an id or get something!
My controller is the defalt api controller
here is my put methode:
public String Put(string id, [FromBody]string value){
//stuff
}
Please can anyone help!?!
Try to consider this post. It describes how to send object or entity to server using retrofit. Also I have found topic that describes how to retrieve json data in server side.
Update
Android side
Try to create simple entity that would contain all data that you would like to send on server
Create simple interface that would be send data to server. Consider next:
public interface UserApi {
#PUT("/api/users/")
Call<Object> sendData(#Body FooRequest body);
}
Get adapter end send request
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://my-address:port")
.build();
UserApi service = retrofit.create(UserApi.class)
service.sendData(new FooRequest());
Server side
Try create apicontroller like this (I`m not sure)
public class UtilityController : ApiController
{
[HttpPut]
public string Put(FooRequest fooRequest)
{
return "bla";
}
}
I hope it would help you!
here is my test project
Good Luck

Android Studio app using Django back-end login authentication?

I've recently been working on an Android app using Android Studio which is using a Django backend. The web application is already in place I just want to make the app in Android for it.
The problem I am running in to, which is mostly because I'm new to app development, is the login authentication. I've researched on this topic here and I understand theoretically how I should go about doing this, but I have not been successful in logging in from my app.
The problem I have is this:
I get a csrf token authentication failure. It states that the cookie is not set. I understand that a post request will return this.
I am always getting a success transition in my doPost method.
I currently am lost in how to check if I have actually logged in or not. And the only solution I thought of for the cookie not being set is to do a Get request, parse the cookie as a string and pass that in to the post request. But I'm not sold on it being the best strategy. The bigger problem is not being able to tell if I have actually logged in or not. How can I check that? I have read posts on kind of explaining how to do this but as a beginner it is hard to translate that to code. How do I check if the user was actually authenticated? Any and all help is appreciated.
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
private final String mEmail;
private final String mPassword;
UserLoginTask(String email, String password) {
mEmail = email;
mPassword = password;
}
#Override
protected Boolean doInBackground(Void... params) {
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("username", mEmail));
postParameters.add(new BasicNameValuePair("password", mPassword));
String response = null;
String get_response = null;
try
{
response = SimpleHttpClient.executeHttpPost(localLoginUrl, postParameters);
Log.d("Login Activity","Post Response is: " + response);
}
catch (Exception e)
{
Log.d("Login Activity","Error is: " + e.toString());
e.printStackTrace();
return false;
}
return true;
}
public static String executeHttpPost(String url,
ArrayList<NameValuePair> postParameters) throws Exception {
BufferedReader in = null;
try {
HttpClient client = getHttpClient();
HttpPost request = new HttpPost(url);
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
request.setEntity(formEntity);
HttpResponse response = client.execute(request);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
String result = sb.toString();
return result;
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The Django view:
def login_view(request): # Login page view
form = login_form()
if request.method == 'POST':
form = login_form(request.POST)
if form.is_valid(): # check if form is valid
user = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password']) # authenthicate the username and password
login(request, user) # login the user
# Once logged in redirect to home page
response = HttpResponseRedirect("/"+some_user_url+"/home")
print "USER KEY IS: %s" % some_user_key
response.set_cookie('some_user_key', value=some_user_value, max_age=some_max_age, secure=SESSION_COOKIE_SECURE, httponly=False)
return response
else:
form = login_form() # Display empty form
return render(request, "login.html", { # loads the template and sends values for the template tags
'form': form,
})
I know the questions was asked quite a long time ago but, since there's no answer, and I'm working quite intensively with Django recently, I thought to share my very basic knowledge, hoping it will be of help for others.
The way you are dealing with the CSRF token is the correct one: first you perform a get of the login page which will give you the CSRF token in the cookie. You store the cookie and the CSRF token and you embed them in the following POST request, together with authentication data. If you get a 200 OK from the server it already means you correctly used the CSRF token, and this is an awesome start :)
In order to troubleshoot whether the user has actually logged in or not, that is whether it's credentials were accepted, you can print out the payload of the HTTP response you obtained from the server.
I use a function which prints me the response of the server in case I get an error code greater than 400. The code is the following:
public static boolean printHTTPErrorMsg(HttpURLConnection c) {
boolean error = false;
StringBuilder builder = new StringBuilder();
try {
builder.append(c.getResponseCode());
builder.append("\n");
builder.append(c.getResponseMessage());
System.out.println("RESPONSE CODE FROM SERVER");
System.out.println(builder);
InputStream _is;
if(c.getResponseCode()>=400){
error = true;
_is = c.getErrorStream();
final BufferedReader reader = new BufferedReader(
new InputStreamReader(_is));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return error;
}
You need to tweak it because when you get a 200 OK from the server, there's no ErrorStream but simply an InputStream. So if you change your if condition to =200 and replace the getErrorStream() with getInputStream() you'll see in the log what is actually the content of the response of the server. Typically, if the login failed, the response will contain most likely the HTML code of the login page with the error message saying you provided wrong credentials.
Hope this helps

Manually parse part of a response when using Retrofit

I'm working with a REST API that returns a JSON document that starts as follows and includes a "collection" of items with string IDs like "ABC". Note the "routes" field, which contains a series of fields called "ABC", "ABD", "ABE" etc, however routes is not represented as an array in the json, so all these
{
"status":true,
"page":1,
"per_page":500,
"total_count":1234,
"total_pages":8,
"total_on_page":500,
"routes":{
"ABC":[
{
"value":22313,
<......>
I'm using Retrofit and the problem is the routes field is not an array (despite the fact conceptually it certainly is) and Retrofit/Gson require me to create a model object for routes with field vars abc, abd, etc - this is not practical as the data changes. For various reasons changing the server API is hard, so I'm looking to work around this on the Android client.
I figure these are options:
Intercept the JSON document before it reaches Gson and tweak the document, possibly with a customised Gson parser, or by intercepting the HTTP response.
Bypass the JSON parsing, and acquire the JSON document from Retrofit (I've yet to figure out how to do this, or if it's possible)
Use some feature of Retrofit I'm unaware of to map field names to a collection.
I'd appreciate help, especially if there's a quick and easy way to resolve this.
It turns out that Retrofit's use of Gson by default makes it fairly easy to add a custom deserialiser to handle the portion of the JSON document that was the problem.
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(ApiDefinition.BASE_URL)
.setConverter(getGsonConverter())
.build();
public Converter getGsonConverter() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(RouteList.class, new RouteTypeAdapter())
.create();
return new GsonConverter(gson);
}
public class RouteTypeAdapter implements JsonDeserializer<RouteList> {
#Override
public RouteList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Gson gson = new Gson();
RouteList routeList = new RouteList();
JsonObject jsonObject = json.getAsJsonObject();
for (Map.Entry<String,JsonElement> elementJson : jsonObject.entrySet()){
RouteList wardsRoutes = gson.fromJson(elementJson.getValue().getAsJsonArray(), RouteList.class);
routeList.addAll(wardsRoutes);
}
return routeList;
}
}
After calling RestService, don't use Model Name as argument, you have to use Default Response class from retrofit library.
RestService Method
#FormUrlEncoded
#POST(GlobalVariables.LOGIN_URL)
void Login(#Field("email") String key, #Field("password") String value, Callback<Response> callback);
Calling method in Activity
getService().Login(email, password, new MyCallback<Response>(context, true, null)
{
#Override
public void failure(RetrofitError arg0)
{
// TODO Auto-generated method stub
UtilitySingleton.dismissDialog((BaseActivity<?>) context);
System.out.println(arg0.getResponse());
}
#Override
public void success(Response arg0, Response arg1)
{
String result = null;
StringBuilder sb = null;
InputStream is = null;
try
{
is = arg1.getBody().in();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
result = sb.toString();
System.out.println("Result :: " + result);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
});

Android: How to get friends birth dates from facebook calendar using Graph API

I'm working on application which need birth dates of all friends. Can some body share code how to get birth dates of all friends using graph API.
I'm using following code:
// start Facebook Login
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
// make request to the
Request.executeMyFriendsRequestAsync(session, new Request.GraphUserListCallback() {
#Override
public void onCompleted(List<GraphUser> users, Response response) {
//Log.d("AL",""+users.size() + response.toString());
for (int i=0;i<users.size();i++){
Log.d("AL",""+users.get(i).toString());
welcome.setText("Done");
}
}
});
}
}
});
And this is only returning friends name and id only. Where I have to set permissions to get friends birthday? I'm new in facebook SDK. And using SDK v3.
graph api is returning following json result
{Response: responseCode: 200, graphObject: GraphObject{graphObjectClass=GraphObject, state={"data":[{"id":"1580811776","name":"Jamal Abdul Nasir"},{"id":"1610349118","name":"Ahmed Nawaz"}],"paging":{"next":"https:\/\/graph.facebook.com\/100004790803061\/friends?format=json&access_token=AAABtTr8g5U4BANiJdCiBFxQeg0l1eqYYzmSWVM8G1UlyAhTtUrAsoEZAgU19dECXTE2nw7pHIz8bDb7OJGM4wAwzusOVZAQN8yaiYVsQZDZD&limit=5000&offset=5000&__after_id=1610349118"}}}, error: null, isFromCache:false}
which does not have birthday.
First define your callback, where you'll get friends and birthday info, if authenticated:
Session.StatusCallback statusCallback = new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
// Private method, to be defined
makeFriendsRequest();
}
}
};
Then, you can open the session and pass in the necessary, "friends_birthday" permissions request:
Session session = new Session(this);
session.openForRead(new Session.OpenRequest(this)
.setCallback(statusCallback)
.setPermissions(Arrays.asList("friends_birthday")));
Finally, here's the post-authentication method you can use to get friends info, including the birthday:
private void makeFriendsRequest() {
Request myFriendsRequest = Request.newMyFriendsRequest(Session.getActiveSession(),
new Request.GraphUserListCallback() {
#Override
public void onCompleted(List<GraphUser> users, Response response) {
if (response.getError() == null) {
// Handle response
}
}
});
// Add birthday to the list of info to get.
Bundle requestParams = myFriendsRequest.getParameters();
requestParams.putString("fields", "name,birthday");
myFriendsRequest.setParameters(requestParams);
myFriendsRequest.executeAsync();
}
Also check out the SessionLoginSample app, bundled with the SDK if you're looking for different ways you can implement Facebook Login.
I suppose try using this:
URL url = "http://YOUR_QUERY_URL_WITH_PARAMS";
InputStream is = null;
URLConnection connection = url.openConnection();
String line;
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader( connection.getInputStream()));
while ((line = reader.readLine()) != null)
{
builder.append(line);
}
String jSONString = builder.toString();
JSONObject jSONObject = new JSONObject(jSONString);
Then take the data received and display it.
Note: I have not tested this code, do not have android device to test on anymore, but should get you pointed in the right direction.

Need help creating Digest authentication for Android

I have this code so far:
private class DownloadWebPageTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... theParams)
{
String myUrl = theParams[0];
String myEmail = theParams[1];
String myPassword = theParams[2];
HttpPost post = new HttpPost(myUrl);
post.addHeader("Authorization","Basic "+ Base64.encodeToString((myEmail+":"+myPassword).getBytes(), 0 ));
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String response = null;
try
{
response = client.execute(post, responseHandler);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null)
{
response += s;
}
}
catch (Exception e)
{
e.printStackTrace();
}
return response;
}
#Override
protected void onPostExecute(String result)
{
}
}
This code does not compile because I am running into confusion at the point of:
response = client.execute(post, responseHandler);
InputStream content = execute.getEntity().getContent();
I got that code from tinkering with various examples, and not sure what Object the client is supposed to be, and whether the first line will just get me the server response, or I have to go the route of getting the InputStream and reading the server response in?
Please help me understand how to do this correctly.
Thank you!
I have managed to use Digest authentication using OkHttp. In this code sample I also use Dagger and Robospice-retrofit. What I did was creating an OkHttp Authenticator and assign it to my custom OkHttp client.
The authenticator class implements an authenticate method that will be called whenever the server encounters a 401 error and expects an Authorization header back (if it expects Proxy-Authorization you should implement the authenticateProxy method.
What it basically does is wrapping calls to the HttpClient DigestScheme and make it usable for OkHttp. Currently it does not increase the nc counter. This could cause problems with your server as it could be interpreted as a replay attack.
public class DigestAuthenticator implements com.squareup.okhttp.Authenticator {
#Inject DigestScheme mDigestScheme;
#Inject org.apache.http.auth.Credentials mCredentials;
#Override
public Request authenticate(Proxy proxy, Response response) throws IOException {
String authHeader = buildAuthorizationHeader(response);
if (authHeader == null) {
return null;
}
return response.request().newBuilder().addHeader("Authorization", authHeader).build();
}
#Override
public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
return null;
}
private String buildAuthorizationHeader(Response response) throws IOException {
processChallenge("WWW-Authenticate", response.header("WWW-Authenticate"));
return generateDigestHeader(response);
}
private void processChallenge(String headerName, String headerValue) {
try {
mDigestScheme.processChallenge(new BasicHeader(headerName, headerValue));
} catch (MalformedChallengeException e) {
Timber.e(e, "Error processing header " + headerName + " for DIGEST authentication.");
}
}
private String generateDigestHeader(Response response) throws IOException {
org.apache.http.HttpRequest request = new BasicHttpRequest(
response.request().method(),
response.request().uri().toString()
);
try {
return mDigestScheme.authenticate(mCredentials, request).getValue();
} catch (AuthenticationException e) {
Timber.e(e, "Error generating DIGEST auth header.");
return null;
}
}
}
The authenticator will then be used in an OkHttpClient built with a provider:
public class CustomClientProvider implements Client.Provider {
#Inject DigestAuthenticator mDigestAuthenticator;
#Override
public Client get() {
OkHttpClient client = new OkHttpClient();
client.setAuthenticator(mDigestAuthenticator);
return new OkClient(client);
}
}
Finally the client is set to the RetrofitRobospice server in the function createRestAdapterBuilder:
public class ApiRetrofitSpiceService extends RetrofitJackson2SpiceService {
#Inject Client.Provider mClientProvider;
#Override
public void onCreate() {
App.get(this).inject(this);
super.onCreate();
addRetrofitInterface(NotificationRestInterface.class);
}
#Override
protected String getServerUrl() {
return Constants.Url.BASE;
}
#Override
protected RestAdapter.Builder createRestAdapterBuilder() {
return super.createRestAdapterBuilder()
.setClient(mClientProvider.get());
}
}
You might want to switch to HttpURLConnection. According to this article its API is simpler than HttpClient's and it's better supported on Android. If you do choose to go with HttpURLConnection, authenticating is pretty simple:
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username", "password".toCharArray());
}
});
After that, continue using HttpURLConnection as usual. A simple example:
final URL url = new URL("http://example.com/");
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
final InputStream is = conn.getInputStream();
final byte[] buffer = new byte[8196];
int readCount;
final StringBuilder builder = new StringBuilder();
while ((readCount = is.read(buffer)) > -1) {
builder.append(new String(buffer, 0, readCount));
}
final String response = builder.toString();
The version of Apache's HttpClient shipped with Android is based on an old, pre-BETA version of HttpClient. Google has long recommended against using it and removed it in Android 6.0. Google's replacement HttpURLConnection does not support HTTP digest authentication, only basic.
This leaves you with a few options, including:
Migrate to HttpURLConnection (as Google recommends) and use a library, bare-bones-digest, for digest authentication. Example below.
Use the OkHttp library instead of HttpURLConnection or HttpClient. OkHttp does not support digest out of the box, but there's a library okhttp-digest that implements a digest authenticator. Example below.
Continue using the (deprecated) HttpClient by explicitly adding the 'org.apache.http.legacy' library to your build, as mentioned in the changelist for Android 6.0.
There is an Apache project for porting newer versions of HttpClient to Android, but the project has been discontinued. Read more on Apache's page on HttpClient for Android.
Implement HTTP digest yourself.
Here is a verbose example of how to authenticate a request using bare-bones-digest and HttpURLConnection (copied from the project's github page):
// Step 1. Create the connection
URL url = new URL("http://httpbin.org/digest-auth/auth/user/passwd");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Step 2. Make the request and check to see if the response contains
// an authorization challenge
if (connection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
// Step 3. Create a authentication object from the challenge...
DigestAuthentication auth = DigestAuthentication.fromResponse(connection);
// ...with correct credentials
auth.username("user").password("passwd");
// Step 4 (Optional). Check if the challenge was a digest
// challenge of a supported type
if (!auth.canRespond()) {
// No digest challenge or a challenge of an unsupported
// type - do something else or fail
return;
}
// Step 5. Create a new connection, identical to the original
// one..
connection = (HttpURLConnection) url.openConnection();
// ...and set the Authorization header on the request, with the
// challenge response
connection.setRequestProperty(
DigestChallengeResponse.HTTP_HEADER_AUTHORIZATION,
auth.getAuthorizationForRequest("GET", connection.getURL().getPath()));
}
Here is an example using OkHttp and okhttp-digest (copied from the okhttp-digest page):
client = new OkHttpClient();
final DigestAuthenticator authenticator = new DigestAuthenticator(new Credentials("username", "pass"));
final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>();
client.interceptors().add(new AuthenticationCacheInterceptor(authCache));
client.setAuthenticator(new CachingAuthenticatorDecorator(authenticator, authCache));
Request request = new Request.Builder()
.url(url);
.get()
.build();
Response response = client.newCall(request).execute();

Categories

Resources