I am working on a Facebook application and am currently trying to have my app tag one of the user's friends. I almost have it working 100%, except when it is supposed to be tagging the person, I instead get an error message that follows:
{"error":{"message":"Unsupported post request.","type":"GraphMethodException","code":100}}
The user and photo IDs are for sure correct, that is not the issue. Otherwise, I'm not sure what else could be causing this error. Code is below for reference. Thanks much!
public void setTag() {
String relativePath = Constants.photoID + "/tags/" + Constants.userID;
Bundle params = new Bundle();
params.putString("x", "5");
params.putString("y", "5");
Constants.mAsyncRunner.request(relativePath, params, "POST", new TagPhotoRequestListener(),
null);
}
public class TagPhotoRequestListener extends BaseRequestListener {
#Override
public void onComplete(final String response, final Object state) {
if (response.equals("true"))
{
String message = "User tagged in photo at (5, 5)" + "\n";
message += "Api Response: " + response;
Log.i("TagPhotoRequestListener", message);
}
else
{
Log.w("TagPhotoRequestListener", "User could not be tagged.");
}
}
public void onFacebookError(FacebookError e) {
Log.w("TagPhotoRequestListener", "Facebook Error: " + e.getMessage());
}
}
EDIT: Here is my code for posting of a picture and getting the photoID. For testing purposes it's just a single photo from my sdcard.
public void postPhoto() {
byte[] data = null;
Bitmap bi = BitmapFactory.decodeFile("/mnt/sdcard/Download/KathleenSchedule.jpg");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bi.compress(Bitmap.CompressFormat.JPEG, 100, baos);
data = baos.toByteArray();
Bundle params = new Bundle();
params.putString(Facebook.TOKEN, Constants.mFacebook.getAccessToken());
params.putString("method", "photos.upload");
params.putByteArray("picture", data);
AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(Constants.mFacebook);
mAsyncRunner.request(null, params, "POST", new PhotoUploadListener(), null);
}
public class PhotoUploadListener extends BaseRequestListener {
#Override
public void onComplete(final String response, final Object state) {
try {
// process the response here: (executed in background thread)
Log.d("PhotoUploadListener", "Response: " + response.toString());
JSONObject json = Util.parseJson(response);
System.out.println(response);
final String photo_id = json.getString("pid");
Constants.photoID = photo_id;
Ok, now your problem is clear.
You are using the photos.upload method which is deprecated:
We are in the process of deprecating the REST API, so if you are
building a new application you shouldn't use this function. Instead
use the Graph API and POST to the photos connection of the User object
Because you are using an old method, you're getting and old response type.
Switch to using the graph api way, and you should get the photo id in the response.
Related
Hi guys I have a problem in codename one api sms
when I push the button he show me this error (error:411 length required)
btsms.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
// String myURL = "https://rest.nexmo.com/sms/json?api_key=*****&api_secret=*****&to=*****" + "&from=*****&text=*****";
String myURL = "https://rest.nexmo.com/sms/json?api_key=d5b95eee&api_secret=93a8c398b48c63bf&to=21625308299&from=NEXMO&text=reservation_annulée";
ConnectionRequest cntRqst = new ConnectionRequest() {
#Override
protected void readResponse(InputStream in) throws IOException {
}
#Override
protected void postResponse() {
Dialog.show("SMS", "sms successfully sent", "OK", null);
}
};
cntRqst.setUrl(myURL);
NetworkManager.getInstance().addToQueue(cntRqst);
}
});
Can you help me please thanks :)
Before I begin you do know there is a Twilio SMS callback library in Codename One right?
You are sending a post call with a URL that's constructed for GET. A minimal fix would be:
cntRqst.setPost(false);
However, I would personally write it as:
ConnectionRequest cntRqst = new ConnectionRequest("https://rest.nexmo.com/sms/json", false) {
// ...
};
cntRqst.addArgument("api_key", API_KEY);
cntRqst.addArgument("api_secret", API_SECRET);
cntRqst.addArgument("to", "21625308299");
cntRqst.addArgument("from", "NEXMO");
cntRqst.addArgument("text", "reservation_annulée");
The advantage of this is the text is implicitly encoded and you can dynamically switch between GET/POST easily.
There is also the newer REST API (assuming result is JSON):
Response<Map> response = Rest.get("https://rest.nexmo.com/sms/json").
queryParam("api_key", API_KEY).
queryParam("api_secret", API_SECRET).
queryParam("to", "21625308299").
queryParam("from", "NEXMO").
queryParam("text", "reservation_annulée").
getAsJsonMap();
I'm making a call using Retrofit's enqueue() method. I'm calling my refreshImages() in my MainActivity's onCreate(), refreshImages() then calls a method refreshImagesIds() which is supposed to make a call out to Flickr's API and return back a PhotosList object, I'll then pull out the Photos from there which will contain a list of Photo objects. My issue is that for some reason the onResponse() inside my enqueue() method is never getting called. When I use the debugger it skips right over it, and when I put Log statements inside they never get written out. I know the endpoint it is hitting is correct because I can see it using OkHttp's logger, and my POJOs all look to be correct for the data being returned.
Any idea why this isn't working? Below are my refreshImages and refreshImagesId. These are both contained in my MainAcitivty and modify class-level variables.
private void refreshImages() {
// make api call
//imageUrls = FlickrServiceManager_withinterface.getKittenImages(8);
refreshImageIds();
List<Photo> photos = photosList.getPhotos().getPhoto();
imageIds = new ArrayList<String>();
for(Photo photo : photos) {
Log.d("TAG", "It is pringint imageIds: " + photo.getId());
imageIds.add(photo.getId());
}
}
private void refreshImageIds() {
Retrofit retrofit = Api.getRestAdapter();
FlickrServiceInterface flickrService = retrofit.create(FlickrServiceInterface.class);
Call<PhotosList> call = flickrService.getPhotos(API_KEY, FORMAT, "1");
imageIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
photosList = response.body();
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
}
And my FlickrServiceInterface:
public interface FlickrServiceInterface {
#GET("?method=flickr.photos.getSizes")
Call<PhotoSizes> getPhotoSizes(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback, #Query("photo_id") String photoId);
#GET("?method=flickr.photos.getRecent")
Call<PhotosList> getPhotos(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback);
}
Change your call to the synchronous retrofit API :
public static List<String> getImageIds(int size) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
PhotosList photosList = call.execute().body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
Please note that you need to call this method on an AsyncTask
EDIT
You could also continue to use enqueue, but you need to provide an "onFinish" hook, so you know when your data has been received and then you "notify" the client with the data:
//interface por communication
public interface ImageIdsCallBack {
public void onFinish( List<String> photoIds );
}
Then you receive this interface and send data:
public static List<String> getImageIds(int size, final ImageIdsCallBack callback) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
PhotosList photosList = response.body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
//send the data to the caller
callback.onFinish(photoIds);
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
calling the method :
getImageIds( 50 , new ImageIdsCallBack() {
public void onFinish( List<String> photoIds ) {
//update UI with photoIds
}
} );
I typically use a library like EventBus to make it easier, I really recommend it to you.
Correct me if I'm wrong, is this on the main thread? That would pose the problem of not waiting for a response.
Consider using async
I'm making a call using Retrofit's enqueue() method. I'm calling my refreshImages() in my MainActivity's onCreate(), refreshImages() then calls a method refreshImagesIds() which is supposed to make a call out to Flickr's API and return back a PhotosList object, I'll then pull out the Photos from there which will contain a list of Photo objects. My issue is that for some reason the onResponse() inside my enqueue() method is never getting called. When I use the debugger it skips right over it, and when I put Log statements inside they never get written out. I know the endpoint it is hitting is correct because I can see it using OkHttp's logger, and my POJOs all look to be correct for the data being returned.
Any idea why this isn't working? Below are my refreshImages and refreshImagesId. These are both contained in my MainAcitivty and modify class-level variables.
private void refreshImages() {
// make api call
//imageUrls = FlickrServiceManager_withinterface.getKittenImages(8);
refreshImageIds();
List<Photo> photos = photosList.getPhotos().getPhoto();
imageIds = new ArrayList<String>();
for(Photo photo : photos) {
Log.d("TAG", "It is pringint imageIds: " + photo.getId());
imageIds.add(photo.getId());
}
}
private void refreshImageIds() {
Retrofit retrofit = Api.getRestAdapter();
FlickrServiceInterface flickrService = retrofit.create(FlickrServiceInterface.class);
Call<PhotosList> call = flickrService.getPhotos(API_KEY, FORMAT, "1");
imageIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
photosList = response.body();
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
}
And my FlickrServiceInterface:
public interface FlickrServiceInterface {
#GET("?method=flickr.photos.getSizes")
Call<PhotoSizes> getPhotoSizes(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback, #Query("photo_id") String photoId);
#GET("?method=flickr.photos.getRecent")
Call<PhotosList> getPhotos(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback);
}
Change your call to the synchronous retrofit API :
public static List<String> getImageIds(int size) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
PhotosList photosList = call.execute().body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
Please note that you need to call this method on an AsyncTask
EDIT
You could also continue to use enqueue, but you need to provide an "onFinish" hook, so you know when your data has been received and then you "notify" the client with the data:
//interface por communication
public interface ImageIdsCallBack {
public void onFinish( List<String> photoIds );
}
Then you receive this interface and send data:
public static List<String> getImageIds(int size, final ImageIdsCallBack callback) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
PhotosList photosList = response.body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
//send the data to the caller
callback.onFinish(photoIds);
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
calling the method :
getImageIds( 50 , new ImageIdsCallBack() {
public void onFinish( List<String> photoIds ) {
//update UI with photoIds
}
} );
I typically use a library like EventBus to make it easier, I really recommend it to you.
Correct me if I'm wrong, is this on the main thread? That would pose the problem of not waiting for a response.
Consider using async
I have an uploader in android which uploads an image file(which is encrypted by an algorithim to 400bytes) but the file has to be decoded to base64 string to be saved to a mysql db as a string and upload the image to a folder.
The problem is that after decoding the file to base64 string it looses its byte encrypted algorithm format.(The image size reduces from 400 bytes to less)
This is what i have done:
Bitmap b = this.toGrayscale(mRegisterImage); //this image file is 400byte encrypted
uploadImage(b);
This is the function uploadimage
public String getStringImage(Bitmap bmp) { //This is what converts the image to 64encoded format string
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos); //Thos is what compresses image hence loosing bytes
byte[] imageBytes = baos.toByteArray();
String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
return encodedImage;
}
private void uploadImage(final Bitmap bmp) {
// Showing the progress dialog
try {
final ProgressDialog loading = ProgressDialog.show(this,
"Uploading fingerprint...", "Please wait...", false, false);
StringRequest stringRequest = new StringRequest(
Request.Method.POST, Config.url,
new Response.Listener<String>() {
#Override
public void onResponse(String s) {
// Disimissing the progress dialog
debugMessage("Return Message: " + s);
loading.dismiss();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
try { // Dismissing the progress dialog
loading.dismiss();
// Showing toast
debugMessage(volleyError.getMessage());
} catch (Exception r) {
debugMessage("onerrorresponse: "+volleyError.getMessage());
}
}
}) {
#Override
protected Map<String, String> getParams()
throws AuthFailureError {
// Converting Bitmap to String
String image = getStringImage(bmp);
// Creating parameters
Map<String, String> params = new Hashtable<String, String>();
// Adding parameters
params.put("image", image);
return params;
}
};
// Creating a Request Queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
// Adding request to the queue
requestQueue.add(stringRequest);
} catch (Exception r) {
debugMessage("out: "+r.getMessage());
}
}
This is the PHP CODE:
$sql ="SELECT id FROM fingerprint ORDER BY id ASC";
$res = mysqli_query($con,$sql);
$id = 0;
while($row = mysqli_fetch_array($res)){
$id = $row['id'];
}
$path = "$id.png";
$actualpath = "http://simplifiedcoding.16mb.com/PhotoUploadWithText/$path";
$sql = "INSERT INTO fingerprint (value) VALUES ('$actualpath')";
if(mysqli_query($con,$sql)){
file_put_contents($path,base64_decode($image));
echo "Successfully Uploaded";
}
Everything works quite fine but is there a way that i can upload the actual image without converting it to a string in android using volley library. The above code compresses the image to the string, How do i change this compression so that the bytes arent lost
Basically no, because Http message body can carry byte data only so can't send any other form of this large data through http protocol.
Http transfer data by using TCP which use commonly switching techniques in this case. Protocols either format data in bit or byte level where byte level is mostly used so if you looking for another way then you are out of luck today
So even if you are using StringRequest and passing data as string parameter eventually your every parameter is converted to byte array type so you can't escape from converting data to bytes.
I want to implement a lazy loading image in my ListView. At first I need to connect to a url and get the urlStrings for all images which belong to an object. I get a jsonString and then parse:
String RESTUrl = new MasterdataDataProvider(mContext).getSyncServicePath() + "PhotoInfo/" + objectEntryID;
List<String> urlStrings = new ArrayList<String>();
try {
HttpGet httpGet = new HttpGet((RESTUrl + "/" + token));
HttpParams httpParameters = new BasicHttpParams();
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
String jsonData = EntityUtils.toString(response.getEntity());
if (!jsonData.equals("[]")) {
GsonPhotoInfo x = new GsonPhotoInfo(new GsonBuilder());
PhotoInfo[] info = x.parseJSON(jsonData);
for(PhotoInfo p : info) {
System.out.println(p.getFileName());
urlStrings.add(photoWebURL + objectDefID + "/" + objectEntryID + "/" + p.getFileName());
}
}
} catch(Exception e) {
e.printStackTrace();
}
As you see in this piece of code I fetch the FileName from jsonData.
Then I need to download the images from urlStrings:
final Handler handler = new Handler() {
#Override
public void handleMessage(Message message) {
ImagePagerAdapter adapter = new ImagePagerAdapter((Drawable[]) message.obj);
viewPager.setAdapter(adapter);
}
};
Thread thread = new Thread() {
#Override
public void run() {
//PARSE THE JSON DATA and FETCH URLStrings (as you see in the piece of code at top)
Drawable[] drawables = new Drawable[urlStrings.size()];
for(int i=0; i< urlStrings.size(); i++)
drawables[i] = fetchDrawable(urlStrings.get(i));
Message message = handler.obtainMessage(1, drawables);
handler.sendMessage(message);
}
};
thread.start();
The code to fetch image is taken from James Wilson answer.
So as you can see there as well, I have to use HTTPClient once again to download every image:
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(urlString);
HttpResponse response = httpClient.execute(request);
return response.getEntity().getContent();
}
The problem is it is not working in my listView. The images are not loaded correctly in listView sometimes, and I am just wondering that is it because of the way that :
I get the urlStrings from jsonData, and then
Download the images from urlStrings one by one.
I mean I connect to REST two times. I am also using a Handler that maybe is not a good option, but actually I tested it with a AsyncTask and I had the same problem.
I appreciate for any idea that could solve my problem.
Addenda:
I found out images are loaded incorrectly when I scroll in the list very fast, otherwise it is fine.
Use UniversalImageLoader library from here. It pretty much works error free. Does memory handling, threading and all other stuff.
Takes 2 minutes to integrate. Try it out !
Oh boy!! you are setting the list adapter every time you download an image. I would suggest you to go with androids tutorial for using a list view and then listview with lazy image loading.
List view
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
Image handling
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
I solved my problem by implementing OnScrollListener for my ListView, and download the image when scroll is in idle mode. But I think the right way is not get the image url in the lazy loading implementation, Maybe the image url need to be included in the main Object.
public static boolean scroll_is_idle = true;
mListView.setOnScrollListener(new OnScrollListener() {
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { }
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_IDLE:
scroll_is_idle = true;
mAdapter.notifyDataSetChanged();
break;
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
scroll_is_idle = false;
break;
case OnScrollListener.SCROLL_STATE_FLING:
scroll_is_idle = false;
break;
}
}
});