I am new to Facebook API. Trying the FQL Query from the Graph API for the first time using this link.
I am trying to get photos from the album with the album id. When I request using Facebook object with https://graph.facebook.com/10150146071791729/photos&access_token=ACCESS_TOKEN URL, I am getting the following response (before parsing to JSON object). {"id":"https://graph.facebook.com/10150146071791729/photos","shares":2}. And I confirmed it by printing the length of the JSON object after parsing, which is 2. When I copy and paste the same URL in the web browser, I am getting the expected response (the response in FQL Query I got). Here is my code.
public void onComplete(Bundle values) {
String token = facebook.getAccessToken();
System.out.println("Token: " + token);
try {
String response = facebook.request("https://graph.facebook.com/10150146071791729/photos&access_token=ACCESS_TOKEN");
System.out.println("response :"+response);
JSONObject obj = Util.parseJson(response);
System.out.println("obj length : " + obj.length());
Iterator iterator = obj.keys();
while(iterator.hasNext()){
String s = (String)iterator.next();
System.out.println(""+s+" : "+obj.getString(s));
}
} catch (Throwable e) {
e.printStackTrace();
}
}
Note: I got access token from the FQL Query which is used in the URL. And I did not wrote any session (login/logout) logic as it is a test project.
Your request is wrong. It should be
"https://graph.facebook.com/10150146071791729/photos?access_token=ACCESS_TOKEN"
Replace the '&' after the photos with a '?'.
Two more things, you're making a Graph API query, not an FQL one.
Second, NEVER post your access tokens publicly. If I wanted to, I can now use your access token to edit your facebook information.
EDIT: When you use the Android Facebook SDK, you do not need to use the full graph path. Instead, use
facebook.request("10150146071791729/photos")
You do not need to add the access token as the Facebook object already has it. Hope this helps.
Because not much code has been provided except for the most relevant one, let me give you a couple of ways you can access Photos from an Album
FIRST METHOD (IF your wish to use the complete URL to make the request)
String URL = "https://graph.facebook.com/" + YOUR_ALBUM_ID
+ "/photos&access_token="
+ Utility.mFacebook.getAccessToken() + "?limit=10";
try {
HttpClient hc = new DefaultHttpClient();
HttpGet get = new HttpGet(URL);
HttpResponse rp = hc.execute(get);
if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String queryPhotos = EntityUtils.toString(rp.getEntity());
Log.e("PHOTOS RESULT", queryPhotos);
}
} catch (Exception e) {
e.printStackTrace();
}
SECOND METHOD (Without using the complete URL as #Vinay Shenoy mentioned earlier)
try {
Bundle paramUserInfo = new Bundle();
paramUserInfo.putString(Facebook.TOKEN, Utility.mFacebook.getAccessToken());
String resultPhotos = Utility.mFacebook.request("YOUR_ALBUM_ID/photos", paramUserInfo, "GET");
Log.e("PHOTOS", resultPhotos);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
On a personal note, I follow the first method almost entirely through my application. It lets me using the Paging for endless ListViews
That being said, when I need some quick data in between somewhere, I do rely on the second method. Both of them work and I hope either (or both) of them helps you.
Related
I know how it can be done for Google Play Store (answer here), but i didn't manage to find a way for AppGallery.
Thank you!
UPDATE #1
Using the answer below i partially solve this with this steps:
Make an API Client with Administrator role, it also works with App Administrator and Operations. (documentaion here: API Client)
Get the access token. (documentaion here: Obtaining a Token)
Get app info. (documentaion here: Querying App Information)
The response from the Querying App Information, have a lot of informations about the app including "versionNumber", but for me it doesn't provide the "versionNumber" (the single info i needed), because this parameter is optional. And now i am stuck again, because i don't understand what i need to change in order to receive this one.
If anyone knows how I can solve this, thank you very much for your help.
UPDATE #2
#shirley's comment was right.
The issue has been fixed in their latest release, and it has been released this month.
You can call the Querying App Information API (GET mode) to query the app details:
public static void getAppInfo(String domain, String clientId, String token, String appId, String lang) {
HttpGet get = new HttpGet(domain + "/publish/v2/app-info?appid=" + appId + "&lang=" + lang);
get.setHeader("Authorization", "Bearer " + token);
get.setHeader("client_id", clientId);
try {
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse httpResponse = httpClient.execute(get);
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
BufferedReader br =
new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), Consts.UTF_8));
String result = br.readLine();
// Object returned by the app information query API, which can be received using the AppInfo object. For details, please refer to the API reference.
JSONObject object = JSON.parseObject(result);
System.out.println(object.get("ret"));
}
} catch (Exception e) {
}
}
They are mentioned here: Completing App Information, Querying App Information.
I am trying to do a http post to my server to check if the login credentials are valid with help of this tutorial. I need to make a request to my server but i have to add Authorization, i get the string with the function getB64Auth from this answer. the function logs the right variable, (the same as i use with postman). But for some reason my program stops running if i run my code. I already tried adding the code from the comments but it didn't help.
What am i doing wrong?
private String getB64Auth (String login, String pass) {
String source=login+":"+pass;
String ret="Basic "+Base64.encodeToString(source.getBytes(),Base64.URL_SAFE| Base64.NO_WRAP);
Log.d("authy", ret);
return ret;
}
/** Called when the user clicks the Login button */
public void login(View view) {
// Getting username and password
EditText userText = (EditText) findViewById(R.id.inputLoginUsername);
EditText passText = (EditText) findViewById(R.id.inputLoginPassword);
String usernameInput = userText.getText().toString();
String passwordInput = passText.getText().toString();
String authorizationString = getB64Auth(usernameInput,passwordInput );
// Do something in response to button
// 1. Create an object of HttpClient
HttpClient httpClient = new DefaultHttpClient();
// 2. Create an object of HttpPost
// I have my real server name down here
HttpPost httpPost = new HttpPost("https://myservername.com/login");
// 3. Add POST parameters
httpPost.setHeader("Authorization", authorizationString);
// 5. Finally making an HTTP POST request
try {
HttpResponse response = httpClient.execute(httpPost);
Log.d("win", "win1");
// write response to log
Log.d("Http Post Response:", response.toString());
} catch (ClientProtocolException e) {
Log.d("fail", "Fail 3");
// Log exception
e.printStackTrace();
} catch (IOException e) {
Log.d("fail", "Fail 4");
// Log exception
e.printStackTrace();
}
}
When i run my code the app stops working, i can find the log authy but i cant find any fail succes logs.
The things i have changed in the example are step 3.
ive added my authorization there.
and removed step 4 cause i dont need it.
Working postman example, with the same request i want to make in android.
You can see I get a response, and only set Authorization on my request.
I cant find any decent post/authorization tutorials so i hope i'm looking at the right direction.
It's an android 4.* project
Just a few suggestions about such issues:
Check permissions (INTERNET is the one you would need)
Applications like Charles / Fiddler let you sniff the Http traffic from the device so you could investigate what is being sent
If the application is crashing - check the LogCat messages (for example it could contain a message explaining which permission is missing)
Regarding this message:
The application may be doing too much work on its main thread.
This usually means that you are doing some heavy operations in the main thread - for example parsing the Json from the Http response. Generally you'd like to do all these operations in a background thread and use the main one to update the UI only.
I am working on an android application that needs to print to a printer. I decided on using the Google Cloud Print, as it seemed easy to set up. Initially, I followed the steps found here for integrating into Android. This works, as in it will print to my desired printer. However, this process is a bit involved for the user. In my case, the process is as follows:
The user selects the print button that I have displayed next to some information.
A Dialog is shown with a preview of what will be printed. There is a button in the ActionBar that says "Print". This begins the process.
A new Activity is displayed showing a list of printers that are connected to that users Google Account. The user must select one.
A new page is shown giving a description of the print job.
The user has to select "Print" in the upper right hand corner.
The print job is started and the printer prints out the picture.
Unfortunately, my client does not want this process. They want the user to click "Print" in step two, and then have the picture printed (steps 1, 2 and 6). Thus, I cannot use Intent provided by Google, I must use the actual API. This requires me to get a Google Auth token, get the desired printer, and submit a print job that way. I do the following:
Use the Google Play Services to retrieve an OAuth token for the users Gmail account.
Get a list of printers using the /search API call.
Submit a print job using the /submit API call.
I have the first two finished. I am just having trouble with the actual printing of the picture. Instead of printing the picture, the byte data of the picture is being printed (Base64 encoded). Here is some code as to how I am sending up the request:
ContentResolver contentResolver = context.getContentResolver();
try {
InputStream is = contentResolver.openInputStream(uri);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = is.read(buffer);
while (n >= 0) {
baos.write(buffer, 0, n);
n = is.read(buffer);
}
is.close();
baos.flush();
content = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + uri.toString(), e);
} catch (IOException e) {
e.printStackTrace();
}
This code retrieves the picture (the variable "uri" is the URI of that file), and turns it into a Base64 encoded string. This is the same method used in the PrintDialogActivity that is provided on the Google Cloud Print page (linked to above). The following is how I send that up:
URL: http://www.google.com/cloudprint/submit?access_token=[AUTH_TOKEN_GOES_HERE]&cookies=false&printerid=[PRINTER_ID_HERE]
HTTP Method: POST
POST Parameters: [printerId=PRINTER_ID_HERE, title=TestPrint, contentType=image/jpeg, capabilities={"capabilities":[{}]}, content=[Base64 Encoded data string is placed here]]
As far as I can tell, this is how it is supposed to be. I am getting a response of {"success":true} when printing. But, as I said above, it prints out the actual Base64 data string. Any help would be appreciated.
EDIT: Using what powerje said below, I managed to fix this. Rather than using the code above, I used the following:
public void submitPrintJobWithFile(String printerId, String title, String token, String filePath, String contentType){
File file = new File(filePath);
// Method that gets the correct headers
List<Header> headers = getHeaders(contentType, token);
// Method that gets the correct post parameters
String url = CLOUDPRINT_URL + PATH_SUBMIT;
List<NameValuePair> postParams = getParams(title, contentType);
String params = "access_token=" + token + "&cookies=false" + "&printerid=" + printerId;
url += params;
response = sendMultipartData(url, file, postParams, headers);
}
private String sendMultipartData(String url, File file, List<NameValuePair> fields, List<Header> headers){
HttpPost post = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
for(NameValuePair pair : fields){
String name = pair.getName();
String value = pair.getValue();
try{
entity.addPart(name, new StringBody(value));
}catch (UnsupportedEncodingException e){
Log.d(TAG, "Error turning pair (name=" + name + ", value=" + value + ") into StringBody.");
}
entity.addPart("content", new FileBody(file));
post.setEntity(entity);
// Finish HttpClient request here...
}
It looks like you need to use multipart encoding, example here:
http://blog.tacticalnuclearstrike.com/2010/01/using-multipartentity-in-android-applications/
FTA:
The files needed are apache-mime4j, httpclient, httpcore and httpmime. All are opensource projects built by the Apache foundation.
Download the 4 files and add them to your project then you should be able to use the following code to post strings and files to pages.
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.tumblr.com/api/write");
try {
MultipartEntity entity = new MultipartEntity();
entity.addPart("type", new StringBody("photo"));
entity.addPart("data", new FileBody(image));
httppost.setEntity(entity);
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
The image variable in this case is a File that contains an image captured by the camera on the phone.
Looking at the Python Sample Code SubmitJob method it seems that only the PDF typs needs to be encoded in Base64.
Answering the question with a bit of an update. As of October 2013, in 4.4 and the support library, there are built in methods to handle printing. See the following documentation for how to do it properly:
PrintHelper - The support Library class to help with printing Bitmaps.
DevBytes: Android 4.4 Printing API - An Android Developers video detailing the APIs
Printing Content - An Android Training guide on how to use these APIs.
I am using the Jackson JSON parser as I heard it was a lot more efficient than the default Android parser. I learned how to use it off this tutorial here
http://www.mkyong.com/java/jackson-streaming-api-to-read-and-write-json/
which is great tutorial if anyone wants to learn how to use Jackson json parser.
However, I am having an issue in that I can parse data fine in Java from a URL, however when I use Jackson with Android, I get null values or the screen just shows up black for some reason.
In order to retrieve the data from the website I am using this code from here
http://www.javacodegeeks.com/2011/01/android-json-parsing-gson-tutorial.html
private InputStream retrieveStream(String url) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(url);
try {
HttpResponse getResponse = client.execute(getRequest);
final int statusCode = getResponse.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w(getClass().getSimpleName(),
"Error " + statusCode + " for URL " + url);
return null;
}
HttpEntity getResponseEntity = getResponse.getEntity();
return getResponseEntity.getContent();
}
catch (IOException e) {
getRequest.abort();
Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
}
return null;
}
Then in my parse data method
InputStream source = retrieveStream(url);
try {
JsonFactory jfactory = new JsonFactory();
JsonParser jParser = jfactory.createJsonParser(source);
Then I parse data as was shown in the tutorial I linked above
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
if ("Name".equals(fieldname)) {
jParser.nextToken();
this.setName(jParser.getText());
}
if ("Number".equals(fieldname)) {
jParser.nextToken();
this.setNumber(jParser.getText());
}
}
The url I am using is a dummy site set up which just has a JSON file on it which I am using to practice Jackson JSON parsing.
Now I know my parse data code is fine, as I in normal Java class, I can parse the data from the website using the code I created, and it works fine.
However if I try to use the code in Android with the code I have just shown, I just get a black screen for some odd reason. I have internet permissions enabled in manifest
Is there something wrong with the http code I have used? If so could someone show me how it should be done? And also why I am getting a black screen, I don't understand why it would show that.
Thanks in advance
Not sure if this is the problem, but your looping construct is unsafe: depending on kind of data you get, it is quite possible that you do not get END_OBJECT as the next token. And at the end of content, nextToken() will return null to indicate end-of-input. So perhaps you get into infinite loop with certain input?
I found the issue, the link was local host which could not be accessed from Emulator. Settings were changed, and can now access link, works perfectly now :D
Lately, I have been working on an app to see if I could do some stuff like a Twitter timeline correctly.
I created a nice little ListView, let some options link to a site, let one option call a Dialog to choose a Twitter account, and accomplished a Twitter feed viewer.
However, it doesn't seem to be possible to actually retrieve a user's timeline without authentication with Twitter? Or is it possible? If so, how do I do that?
Can I retrieve and display a user's Twitter feed without authentication, and how?
Yes, you can either use the twitter search API, which returns json formatted data, which you must parse, just search the documentation. Alternatively, you can use a direct link to a user's timeline like so:
https://twitter.com/statuses/user_timeline/user.json
EDIT: This returns the response as .json for me, next it needs to be parsed. Make sure you are parsing the response AFTER it has been received, it looks like you are starting the request and then jumping to parsing it, before the request is complete.
public ArrayList<Tweet> getTweets(String Account, int page) {
String accountUrl = "http://search.twitter.com/search.json?q=#"
+ Account + "&rpp=100&page=" + page;
ArrayList<Tweet> tweets = new ArrayList<Tweet>();
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(accountUrl);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = null;
try{
responseBody = client.execute(get, responseHandler);
Toast.makeText(this, responseBody, Toast.LENGTH_LONG).show();
// parse response, return arraylist
}catch(Exception ex) {
ex.printStackTrace();
}
}