Anybody can please help in Android + Twitter Integration using OAuth.
I already worked on http://github.com/brione/Brion-Learns-OAuth and getting the error listed below, when I am posting status update...
WARN/System.err(190): org.apache.http.client.HttpResponseException: Unauthorized
WARN/System.err(190): at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:71)
WARN/System.err(190): at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:59)
WARN/System.err(190): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657)
WARN/System.err(190): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627)
WARN/System.err(190): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616)
WARN/System.err(190): at com.test.twitter.BLOA$PostTask.doInBackground(BLOA.java:343)
WARN/System.err(190): at com.test.twitter.BLOA$PostTask.doInBackground(BLOA.java:1)
WARN/System.err(190): at android.os.AsyncTask$2.call(AsyncTask.java:185)
WARN/System.err(190): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256)
WARN/System.err(190): at java.util.concurrent.FutureTask.run(FutureTask.java:122)
WARN/System.err(190): at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648)
WARN/System.err(190): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673)
WARN/System.err(190): at java.lang.Thread.run(Thread.java:1060)
I succeed with OAuth Authentication and getting user_secret and user_token and stored in preferences...
So the issue is with http posting using OAuth header...
and My Http Post Method is as :
private class PostTask extends AsyncTask<String, Void, JSONObject> {
ProgressDialog postDialog;
#Override
protected void onPreExecute() {
postDialog = ProgressDialog.show(BLOA.this,
getText(R.string.tweet_progress_title),
getText(R.string.tweet_progress_text), true, // indeterminate
// duration
false); // not cancel-able
}
#Override
protected JSONObject doInBackground(String... params) {
JSONObject jso = null;
try {
HttpPost post = new HttpPost(
"http://twitter.com/statuses/update.json");
LinkedList<BasicNameValuePair> out = new LinkedList<BasicNameValuePair>();
out.add(new BasicNameValuePair("status", params[0]));
post.setEntity(new UrlEncodedFormEntity(out, HTTP.UTF_8));
post.setParams(getParams());
// sign the request to authenticate
mConsumer.sign(post);
String response = mClient.execute(post,
new BasicResponseHandler());
jso = new JSONObject(response);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
}
return jso;
}
// This is in the UI thread, so we can mess with the UI
protected void onPostExecute(JSONObject jso) {
postDialog.dismiss();
if (jso != null) { // authorization succeeded, the json object
// contains the user information
mEditor.setText("");
mLast.setText(getCurrentTweet(jso));
} else {
mLast.setText(getText(R.string.tweet_error));
}
}
}
Although you are received the user_secret and user_token successfully in onResume(), are you sure your original objects are still the same? I had this problem in my Android app. I would create the objects, but when onResume() was called it was a totally new instance of the Activity because it was free'd from memory when the browser launched. So when I tried to set the returned secret/token pair it wouldn't work. This is more likely to happen on a device with limited memory. Some people choose to persist the necessary info between calls and others decide to not launch the default browser intent, but rather host an embedded webview so their original signpost-oauth objects don't go out of scope.
OAuth instance state in Android
Not sure if this is the issue, but maybe worth a look.
You need to add the oauth information to the headers of the http request using post.addHeader(). To know which things to add to the headers, take a look here: http://dev.twitter.com/pages/auth
Please describe what Client/Consumer/Provider you are using, they must be DefaultHttpClient/CommonsHttpOAuthConsumer/CommonsHttpOAuthProvider to work properly for sure.
Ensure you call consumer.setTokenWithSecret(oToken, oTokenSecret); before calling this code.
Also, is post.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false); exists in your post params?
What's the reason for using empty BasicResponseHandler, it handles nothing and it can be omitted in execute call, I suppose.
And, may be a dumb question, may be you are overwriting params when calling setParams(...) after setEntity(...)
I have 2 tutorials for 2 different Java libs. First one (dated) is here, and 2nd one here with Scribe. It's for LinkedIn but it would be very easy to switch to Twitter. I would go with #2
Related
I have 3 tabs in my app, each having its own Fragment. I need to populate each tab's Fragment with data that needs to be retrieved from my website's REST API.
To my understanding, the onCreate/onCreateView method in the Fragment class is where I should request the JSON data (how do I request it?).
Then I would loop through the data and insert it into separate lists or cards (how do I do this?).
Sorry for the beginner questions, but I'm not sure where to begin.
There are two ways to do this
1) through native android
private void makeGetRequest() {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://www.example.com");
// replace with your url
HttpResponse response;
try {
response = client.execute(request);
Log.d("Response of GET request", response.toString());
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2) use third party libraries.Please refer this url https://github.com/square/retrofit
Example
https://github.com/square/retrofit/blob/master/samples/src/main/java/com/example/retrofit/SimpleService.java
This library will do all the things like GET,POST,Sync,Async and Error Handling.
you have to use AsyncTask When youre requesting anything from server, Asynctask runs in backgrouns so your UI thread will no be blocked by it.
Otherwise you can try using Volly library dosen't need an AsyncTask to work. It will work in background thread anyway '
It also provides you with sucess failure handlers(if youre into ajax and all it'll easier for you)
take a look at Volly Library
I'm trying to setup a survey that my app users can take that will post the results to a rails app. The survey/questions/answers are built in the rails app, then displayed in the Android app. After the user answers each question it should post back to the server.
I suspect that it's something to do with my create method (the uncommented line works for creating a choice in the rails app but not for the Android post and the commented line appears to work for neither) but I'm relatively new to Android/Rails so any help would be much appreciated!
Here's my ChoicesController:
class ChoicesController < ApplicationController
# POST /choices
# POST /choices.json
def create
#question = Question.find(params[:question_id])
#choice = #question.choices.build(choice_params)
#choice.answer = Answer.find(params[:choice][:answer_id])
# #choice.answer = Answer.find(params[:answer_id])
respond_to do |format|
if #choice.save
format.html { redirect_to question_choices_path, notice: 'Choice was successfully created.' }
format.json { render action: 'show', status: :created, location: #choice }
else
format.html { render action: 'new' }
format.json { render json: #choice.errors, status: :unprocessable_entity }
end
end
end
My choice model:
class Choice < ActiveRecord::Base
belongs_to :question
belongs_to :answer
belongs_to :user
validates :question_id, presence: true
validates :answer_id, presence: true
end
Here's how I'm creating/posting my json in Android:
public boolean postChoice(String apiKey) {
boolean choicePosted = false;
try {
post();
} catch (Exception e) {
e.printStackTrace();
}
choicePosted = true;
return choicePosted;
}
public static void post() {
Map<String, String> choice = new HashMap<String, String>();
choice.put("question_id", "6");
choice.put("answer_id", "15");
String json = new GsonBuilder().create().toJson(choice, Map.class);
makeRequest("http://localhost:3000/choices/", json);
}
public static HttpResponse makeRequest(String uri, String json) {
try {
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(new StringEntity(json));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
return new DefaultHttpClient().execute(httpPost);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Any help is much appreciated!
One big problem with your code is:
} catch (Exception e) {
e.printStackTrace();
}
You are swallowing all exceptions and my guess you are also swallowing the problem exception. You should look into logs what exception is recorded and also not use catch (Exception e) but instead have explicit exception.
Without actual exception it hard to diagnose, but my guess is that you are making this http request inside UI thread and Android framework explicitly forbids it (it makes your app non-responsive) and throws an exception.
Turns out the biggest problem I had was that I was not sending a CSRF token with my POST. including skip_before_action :verify_authenticity_token solved my problem. Since it's an API I have a few other security verification piece in place, but CSRF really only applies to web forms anyway.
I am trying to use graph batch api , is there any reference code ? how do we set the
parameters ? Has anyone used batch api with reference to android apps
I am using this link
and I've also have used individual graph apis such as
fbApiObj.request("me/notifications");
fbApiObj.request("me/home");fbApiObj.request("me/friends");
I want to batch them. The explanation provided in the link above is not very clear as to how to convert to api calls.
What you need to do is build a JSONArray for your request, and then convert that JSONArray to a string before you send it to the server using HTTPS POST. For each request, make a JSONObject according to the Facebook API (link previously posted), then add all these JSONObjects to a JSONArray and use the Facebook SDK's built-in "openUrl" method (located in the Util class inside the SDK).
Here's a small example that I built for testing the batch.
JSONObject me_notifications = new JSONObject();
try {
me_notifications.put("method", "GET");
me_notifications.put("relative_url", "me/notifications");
} catch (JSONException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
JSONObject me_home = new JSONObject();
try {
me_home.put("method", "GET");
me_home.put("relative_url", "me/home");
} catch (JSONException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
JSONObject me_friends = new JSONObject();
try {
me_friends.put("method", "GET");
me_friends.put("relative_url", "me/friends");
} catch (JSONException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
JSONArray batch_array = new JSONArray();
batch_array.put(me_home);
batch_array.put(me_notifications);
batch_array.put(me_friends);
new FacebookBatchWorker(this, mHandler, false).execute(batch_array);
And the FacebookBatchWorker is simply an asynctask (just use any threading you want really...). The important part is the HTTPS request, I used the already available ones inside the facebook SDK, like this.
The "params[0].toString()" is the JSONArray I sent to the AsyncTask, we need that converted to a String for the actual post request.
/* URL */
String url = GRAPH_BASE_URL;
/* Arguments */
Bundle args = new Bundle();
args.putString("access_token", FacebookHelper.getFacebook().getAccessToken());
args.putString("batch", params[0].toString());
String ret = "";
try {
ret = Util.openUrl(url, "POST", args);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Hopefully you'll get something out of this...
The batch requests from the facebook graph API are available through HTTP requests. It does not matter whether the request comes from an android phone or not.
It is a quite recent feature and the facebook android sdk has not been updated recently in github, so you will need to handle those requests directly.
Reference: http://developers.facebook.com/docs/reference/api/batch/
First time asking a question here. Usually I can find my answer without having to ask, but this time I'm stuck and can't figure out what I'm missing.
I'm just trying to have my Android app fill out a form on a website and submit it. I don't need the app to do anything with any data being sent back, just fill out the form and submit it. Basically I'm trying to collect the results of a voting app. I thought form submission would be simple so I created a Google Spreadsheet and made a form out of it. I figured I'd point the Android app to the form and then I would have all the data in the spreadsheet for later viewing. I can't get the Android app to actually fill out the form though. Here's the resources.
Form
Spreadsheet
private void submitVote(String outcome) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://spreadsheets.google.com/spreadsheet/formResponse?hl=en_US&formkey=dDlwZzh4bGFvNFBxUmRsR0d2VTVhYnc6MQ&ifq");
List<BasicNameValuePair> results = new ArrayList<BasicNameValuePair>();
results.add(new BasicNameValuePair("entry.0.single", cardOneURL));
results.add(new BasicNameValuePair("entry.1.single", outcome));
results.add(new BasicNameValuePair("entry.2.single", cardTwoURL));
try {
post.setEntity(new UrlEncodedFormEntity(results));
} catch (UnsupportedEncodingException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "An error has occurred", e);
}
try {
client.execute(post);
} catch (ClientProtocolException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "An error has occurred", e);
} catch (IOException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "An error has occurred", e);
}
}
I made both the form and the spreadsheet public so feel free to mess around with it and try and get it to work yourself.
I get no errors from my program, no compile errors, no errors in DDMS. When I actually run the program and click the button that executes this code I can see the delay since right now this is in the UI thread, so I know it's executing it. It appears as if everything is working perfectly, but my spreadsheet doesn't update at all.
Any thoughts? I'm sure it's something stupid that I'm missing, but any help would be appreciated.
Here's the updated code with lots of logging and debugging stuff.
private void submitVote(String outcome) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://spreadsheets.google.com/spreadsheet/formResponse?hl=en_US&formkey=dDlwZzh4bGFvNFBxUmRsR0d2VTVhYnc6MQ&ifq");
List<BasicNameValuePair> results = new ArrayList<BasicNameValuePair>();
results.add(new BasicNameValuePair("entry.0.single", cardOneURL));
results.add(new BasicNameValuePair("entry.1.single", outcome));
results.add(new BasicNameValuePair("entry.2.single", cardTwoURL));
try {
post.setEntity(new UrlEncodedFormEntity(results));
} catch (UnsupportedEncodingException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "An error has occurred", e);
}
try {
HttpResponse httpResponse = client.execute(post);
Log.e("RESPONSE", "info: " + httpResponse);
BufferedReader rd = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
String line;
while ((line = rd.readLine()) != null) {
Log.i("words", line);
}
Intent intent = new Intent(this, ReadingView.class);
intent.putExtra("html", line);
startActivity(intent);
} catch (ClientProtocolException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "client protocol exception", e);
} catch (IOException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "io exception", e);
}
}
I use ReadingView.class for something else in my app, but hijacked it for this logging purpose right now. It only has an onCreate() method, which is below.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.readingview);
WebView mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
//mWebView.loadUrl(getIntent().getExtras().getString("url"));
mWebView.loadData(getIntent().getExtras().getString("html"), "text/html", "utf-8");
}
Also worth noting that in the DDMS it only logs one output of line. I believe this is just because the html code is returned all as one line. Correct me if I'm wrong.
So I finally figured out what was going on. Through messing with manually encoding answers to the end of the form POST url I was able to find that the url it gave when viewing the source had encoding issues of it's own in it.
Here's the url from source:
<form action="https://spreadsheets.google.com/spreadsheet/formResponse?hl=en_US&formkey=dDlwZzh4bGFvNFBxUmRsR0d2VTVhYnc6MQ&ifq" method="POST" id="ss-form">
But here's what it needs to be to actually work in the above code:
https://spreadsheets.google.com/spreadsheet/formResponse?hl=en_US&formkey=dDlwZzh4bGFvNFBxUmRsR0d2VTVhYnc6MQ
The extra amp; was what was messing it up. For whatever reason it works without the last &ifq too, so I left that off. Anyway, here's completed code:
private void submitVote(String outcome) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://spreadsheets.google.com/spreadsheet/formResponse?hl=en_US&formkey=dDlwZzh4bGFvNFBxUmRsR0d2VTVhYnc6MQ");
List<BasicNameValuePair> results = new ArrayList<BasicNameValuePair>();
results.add(new BasicNameValuePair("entry.0.single", cardOneURL));
results.add(new BasicNameValuePair("entry.1.single", outcome));
results.add(new BasicNameValuePair("entry.2.single", cardTwoURL));
try {
post.setEntity(new UrlEncodedFormEntity(results));
} catch (UnsupportedEncodingException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "An error has occurred", e);
}
try {
client.execute(post);
} catch (ClientProtocolException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "client protocol exception", e);
} catch (IOException e) {
// Auto-generated catch block
Log.e("YOUR_TAG", "io exception", e);
}
}
Hope this helps someone else when trying to work with Google Spreadsheet Forms. And thanks to #pandre for pointing me in the right direction.
The format, entry.0.single might not work in many cases. You must always find the proper id of the elements to create your POST request. This article provides the proper way to post data to a Google docs sheet via android app.
Have a look at the source for Acra. This uploads stack traces to a Google spreadsheet.
You probably are not seing errors because you are printing exceptions in the wrong way.
You are using e.printStackTrace(); which does not appear in DDMS/Logcat.
You should use instead
Log.e("YOUR_TAG, "An error has occurred", e);
which will log your error in DDMS/Logcat. You should see the stacktrace of the exception, and it will help you understand what's wrong.
EDIT:
Have you checked what is returned in client.execute(post); ?
You should check what is being returned in the POST response by doing:
HttpResponse httpResponse = client.execute(post);
You can also run the application in debug mode and check where it is crashing / stopping
So the cardOneUrl's are text edit fields in a layout.xml "results.add(new BasicNameValuePair("entry.0.single", cardOneURL));" Thanks, Joe
I am trying to implement asynchronus http client for Android and I am haveing a trouble with type mismatch:
The method execute(HttpUriRequest) in the type HttpClient is not applicable for the arguments (HttpRequest)
I am doing all based on this tutorial: http://blog.androgames.net/12/retrieving-data-asynchronously/
Have found a type in AsynchronousSender - private HttpRequest request; but I have still problem with above which occurs in:
public void run() {
try {
final HttpResponse response;
synchronized (httpClient) {
response = getClient().execute(request); //<-- here is that problem
}
// process response
wrapper.setResponse(response);
handler.post(wrapper);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Can you suggest anything ?
cheers,
/Marcin
The code snippets on http://blog.androgames.net/12/retrieving-data-asynchronously/ are wrong. To fix it just replace HttpRequest with HttpUriRequest since the method signature is: HttpClient#execute(HttpUriRequest). It shouldn't be any problem since most requests you work with are HttpUriRequest instances.