Android - Tumblr Access Token via OAuth - android

I am trying to allow Android users to post to their Tumblr blogs using my app. I am able to launch Tumblr, enter my username and password, and log in, however the problem is the Access Token I receive appears to be invalid (I get a 401 - Unauthorized when I use it with any of Tumblr's API calls).
Below is the code I am using. I am able to authenticate with Twitter, but Tumblr is giving me difficulties. If anyone has any ideas, suggestions, or improvements, they would be much appreciated. Thanks!
public final class TumblrWebView extends Activity {
private final String TAG = getClass().getSimpleName();
OAuth10Service service;
public final static String PARAMETER_CONSUMER_KEY = "CONSUMER_KEY";
public final static String PARAMETER_CONSUMER_SECRET = "CONSUMER_SECRET";
public final static String PARAMETER_CALLBACK_URL = "CALLBACK_URL";
private String consumerKey;
private String consumerSecret;
private String callbackUrl;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web_view);
/*
* Get params
*/
Intent intent = getIntent();
consumerKey = intent.getStringExtra(PARAMETER_CONSUMER_KEY);
consumerSecret = intent.getStringExtra(PARAMETER_CONSUMER_SECRET);
callbackUrl = intent.getStringExtra(PARAMETER_CALLBACK_URL);
service = OAuthService.newInstance(new TumblrApi(), consumerKey, consumerSecret, new OAuth10ServiceCallback() {
#Override
public void onOAuthAccessTokenReceived(OAuth10Token token) {
complete(token);
Log.i(TAG, "Access token recieved");
// System.out.println("token recieved " + token.getAccessToken());
// System.out.println("token recieved " + token.getUserSecret());
}
#Override
public void onOAuthRequestTokenReceived() {
loadWebView();
Log.i(TAG, "Request token recieved");
}
#Override
public void onOAuthRequestTokenFailed(HootResult result) {
Log.e(TAG, "Token request failed " + result.getException());
}
#Override
public void onOAuthAccessTokenFailed(HootResult result) {
Log.e(TAG, "Token access failed " + result);
}
});
service.start();
}
#SuppressLint("SetJavaScriptEnabled")
private void loadWebView() {
final WebView webview = (WebView) findViewById(R.id.web_view);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Checking for our successful callback
if(url.startsWith(callbackUrl)) {
webview.setVisibility(View.GONE);
Log.d(TAG, "token url " + url + " " + service.getOAuthAccessToken(url));
} else {
Log.d(TAG, "token url");
}
return super.shouldOverrideUrlLoading(view, url);
}
});
webview.loadUrl(service.getAuthorizeUrl());
}
private void complete(OAuth10Token token) {
Intent resultIntent = new Intent();
resultIntent.putExtra(TumblrUtils.PREF_TUMBLR_ACCESS, token.getAccessToken());
resultIntent.putExtra(TumblrUtils.PREF_TUMBLR_SECRET, token.getUserSecret());
setResult(RESULT_OK, resultIntent);
finish();
}
}
EDIT: A helper class
public class TumblrUtils {
// Consumer Key and Secret
private static final String TUMBLR_CONSUMER_KEY = "{ ENTER TUMBLR CONSUMER KEY }";
private static final String TUMBLR_CONSUMER_SECRET = "{ ENTER TUMBLR CONSUMER SECRET }";
// Callback URL
private static final String TUMBLR_CALLBACK_URL = "http://example.com";
// Request Code
public static final int TUMBLR_REQUEST_CODE = 87; /* 87 - TR */
// Preference Constants
public static final String PREF_TUMBLR_USER = "tumblr_user";
public static final String PREF_TUMBLR_ACCESS = "tumblr_access_token";
public static final String PREF_TUMBLR_SECRET = "tumblr_secret_token";
public static final String TUMBLR_REQUEST_URL = "http://www.tumblr.com/oauth/request_token";
public static final String TUMBLR_ACCESS_URL = "http://www.tumblr.com/oauth/access_token";
public static final String TUMBLR_AUTHORIZE_URL = "http://www.tumblr.com/oauth/authorize";
private static OAuthConsumer tumblrConsumer;
private static String tumblrHost;
private static String tumblrToken;
private static String tumblrTokenSecret;
private static String getConsumerKey() {
return TUMBLR_CONSUMER_KEY;
}
private static String getConsumerSecret() {
return TUMBLR_CONSUMER_SECRET;
}
private static String getCallbackUrl() {
return TUMBLR_CALLBACK_URL;
}
public static String getRequestUrl() {
return TUMBLR_REQUEST_URL;
}
public static String getAccessUrl() {
return TUMBLR_ACCESS_URL;
}
public static String getAuthorizeUrl() {
return TUMBLR_AUTHORIZE_URL;
}
public static OAuthConsumer getTumblrConsumer() {
return tumblrConsumer;
}
public static String getTumblrHost() {
return tumblrHost;
}
public static void setTumblrHost(String host) {
TumblrUtils.tumblrHost = host;
}
public static String getTumblrToken() {
return tumblrToken;
}
public static String getTumblrTokenSecret() {
return tumblrTokenSecret;
}
public static Intent getTumblrIntent(Context activity) {
Intent TumblrIntent = new Intent(activity, TumblrWebView.class);
TumblrIntent.putExtra("CONSUMER_KEY", getConsumerKey());
TumblrIntent.putExtra("CONSUMER_SECRET", getConsumerSecret());
TumblrIntent.putExtra("CALLBACK", getCallbackUrl());
return TumblrIntent;
}
public static OAuthConsumer saveTumblrResult(SharedPreferences settings,
String access_token, String secret_token) {
Editor editor = settings.edit();
editor.putString(PREF_TUMBLR_ACCESS, access_token);
editor.putString(PREF_TUMBLR_SECRET, secret_token);
editor.commit();
return saveTumblrResult(access_token, secret_token);
}
public static OAuthConsumer saveTumblrResult(String stringExtra1, String stringExtra2) {
tumblrToken = (stringExtra1);
tumblrTokenSecret = (stringExtra2);
tumblrConsumer = new CommonsHttpOAuthConsumer(
getConsumerKey(), getConsumerSecret());
tumblrConsumer.setTokenWithSecret(
tumblrToken, tumblrTokenSecret);
return tumblrConsumer;
}
}
EDIT: TumblrWebActivity - startActivityForResult
startActivityForResult(
TumblrUtils.getTumblrIntent(Settings_ShareSettings.this),
EDIT: TumblrWebActivity - onActivityResult
TumblrUtils.TUMBLR_REQUEST_CODE);
TumblrUtils.saveTumblrResult(mPrefs,
data.getStringExtra(TumblrUtils.PREF_TUMBLR_ACCESS),
data.getStringExtra(TumblrUtils.PREF_TUMBLR_SECRET));
new TumblrTask("https://api.tumblr.com/v2/user/info").execute();
EDIT: GetUserInfo - AsyncTask
private final class TumblrTask extends AsyncTask<String, Void, String> {
String url;
public TumblrTask(String url) {
this.url = url;
}
#Override
protected String doInBackground(String... params) {
String result = "";
HttpClient httpclient = GlobalContext.getHttpClient();
HttpRequestBase request = new HttpGet(url);
try {
TumblrUtils.getTumblrConsumer().sign(request);
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
}
try {
HttpResponse response = httpclient.execute(request, GlobalContext.getLocalContext());
HttpEntity entity = response.getEntity();
InputStream instream = entity.getContent();
result = GlobalContext.convertStreamToString(instream);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject jObject = new JSONObject(result.trim());
System.out.println(jObject);
if(jObject.has("response")) {
JSONObject jResponse = jObject.getJSONObject("response");
System.out.println(jResponse);
if(jResponse.has("user")) {
JSONObject jUser = jResponse.getJSONObject("user");
System.out.println(jUser);
tumblr_name = jUser.getString("name");
TumblrUtils.saveTumblrResult(mPrefs, tumblr_name);
tvTumblr.setText(tumblr_name);
ibTumblr.setSelected(true);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
EDIT: NOTE: Requires AndrOAuth

As it turns out, the Access Token and Access Token Secret returned were valid. The problem was that I was not signing the request with the Access Token Secret.

Related

Withings API integration in android

I am building Android App which shows Withings user's activity data in my Application.
But when I am trying to call refresh_token url:
https://oauth.withings.com/account/request_token?oauth_callback=******&oauth_consumer_key=******&oauth_nonce=******&oauth_signature=CcMrI7JaI8M5tEenye3s95wx%2BZ4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1477386344&oauth_version=1.0
Then I am getting Invalid Signature response like below:
{
"status":0,
"message":"Invalid signature :\n CcMrI7JaI8M5tEenye3s95wx+Z4= .. \n{\"oauth_callback\":\"******\",\"oauth_consumer_key\":\"ce54bd6c671546ef8f8d394c0db4bd86688289d5f7fb39f371c5ebce4d01\",\"oauth_nonce\":\"f339febe0fdf4b53b953501e45a049db\",\"oauth_signature\":\"CcMrI7JaI8M5tEenye3s95wx+Z4=\",\"oauth_signature_method\":\"HMAC-SHA1\",\"oauth_timestamp\":\"1477386344\",\"oauth_version\":\"1.0\"}\n{\"base_string\":\"GET&https%3A%2F%2Foauth.withings.com%2Faccount%2Frequest_token&oauth_callback%3D******%26oauth_consumer_key%3D******%26oauth_nonce%3Df339febe0fdf4b53b953501e45a049db%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1477386344%26oauth_version%3D1.0\"}\n{\"key\":\"******\",\"secret\":\"******\",\"callback_url\":null}"
}
First of all you can use the scribe lib
On my sample code I have an Authentication Activity that has an WebView that the user uses to verify the app. Then that Authentication Activity sends back to the MainActivity the response.
On my example I am storing locally on a DB the authenticated user to not ask every time the credentials.
Also I am sending the access token to python server that will get all data stored on Withings Cloud to save it to my Server DB and represent them on a Graph Activity. {I have removed that part}
Because of the copy paste maybe something is missing but most of the code is here
public class WithingsApi extends DefaultApi10a {
private static final String AUTHORIZATION_URL ="https://oauth.withings.com/account/authorize?oauth_token=%s";
private static final String apiKey = "API_KEY";
private static final String apiSecret = "API_SECRET";
#Override
public String getRequestTokenEndpoint() {
return "https://oauth.withings.com/account/request_token";
}
#Override
public String getAccessTokenEndpoint() {
return "https://oauth.withings.com/account/access_token";
}
#Override
public String getAuthorizationUrl(Token requestToken) {
return String.format(getAUTHORIZATION_URL(), requestToken.getToken());
}
public static String getKey(){
return apiKey;
}
public static String getSecret(){
return apiSecret;
}
public static String getAUTHORIZATION_URL() {
return AUTHORIZATION_URL;
}
}
#SuppressLint("SetJavaScriptEnabled")
public class AuthenticationActivity extends Activity {
final String LOGTAG = "WITHINGS";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_authentication);
final WebView wvAuthorise = (WebView) findViewById(R.id.wvAuthorise);
wvAuthorise.getSettings().setJavaScriptEnabled(true);
wvAuthorise.setWebViewClient(new MyWebViewClient(wvAuthorise));
MainActivity.service = new ServiceBuilder().provider(WithingsApi.class)
.apiKey(WithingsApi.getKey())
.apiSecret(WithingsApi.getSecret())
.build();
new Thread(new Runnable() {
public void run() {
MainActivity.requestToken = MainActivity.service.getRequestToken();
final String authURL = MainActivity.service.getAuthorizationUrl(MainActivity.requestToken);
wvAuthorise.post(new Runnable() {
#Override
public void run() {
wvAuthorise.loadUrl(authURL);
}
});
}
}).start();
}
class MyWebViewClient extends WebViewClient{
WebView wvAuthorise;
MyWebViewClient(WebView wv){
wvAuthorise = wv;
}
#Override
public void onPageFinished(WebView view, String url) {
getUSERID(url);
}
}
private void getUSERID(final String url) {
try {
String divStr = "userid=";
int first = url.indexOf(divStr);
if(first!=-1){
final String userid = url.substring(first+divStr.length());
Intent intent = new Intent();
intent.putExtra("USERID",userid);
setResult(RESULT_OK,intent);
finish();
}
else
{
//...
}
} catch (Exception e) {
Log.e(LOGTAG,e.getMessage());
//...
}
}
}
public class MainActivity extends FragmentActivity {
public static OAuthService service;
public static Token requestToken;
String secret, token;
Token accessToken;
String userId = "";
private UsersDataSource datasource;
private TextView nameTV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_mainActivity = this;
nameTV = (TextView) findViewById(R.id.nameTitleTextView);
nameTV.setText("--");
getCredentials();
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == AUTHENTICATION_REQUEST) {
if (resultCode == RESULT_OK) {
Bundle extras = intent.getExtras();
if (extras != null) {
userId = extras.getString("USERID");
getAccessTokenThread.execute((Object) null);
}
}
}
}
#Override
protected void onResume() {
datasource.open();
super.onResume();
}
#Override
protected void onPause() {
datasource.close();
super.onPause();
}
private void getCredentials() {
try {
datasource = new UsersDataSource(this);
datasource.open();
List<User> users = datasource.getAllUsers();
if (users.isEmpty()) {
startAuthenticationActivity();
} else {
// TODO load all users and if isn't anyone correct
// startAuthenticationActivity
secret = users.get(0).getSecret();
token = users.get(0).getToken();
userId = users.get(0).getUserId();
Log.i(LOGTAG, "secret : " + secret);
Log.i(LOGTAG, "token : " + token);
Log.i(LOGTAG, "userId : " + userId);
try {
service = new ServiceBuilder().provider(WithingsApi.class)
.apiKey(WithingsApi.getKey())
.apiSecret(WithingsApi.getSecret()).build();
accessToken = new Token(token, secret);
loadData();
} catch (Exception ex) {
startAuthenticationActivity();
}
}
} catch (Exception ex) {
Log.e(LOGTAG, "try on create" + ex.getLocalizedMessage());
}
}
private void startAuthenticationActivity() {
Intent intent = new Intent(this,
ics.forth.withings.authentication.AuthenticationActivity.class);
startActivityForResult(intent, AUTHENTICATION_REQUEST);
}
AsyncTask<Object, Object, Object> getAccessTokenThread = new AsyncTask<Object, Object, Object>() {
#Override
protected Object doInBackground(Object... params) {
accessToken = service
.getAccessToken(requestToken, new Verifier(""));
secret = accessToken.getSecret();
token = accessToken.getToken();
return null;
}
#Override
protected void onPostExecute(Object result) {
// authentication complete send the token,secret,userid, to python
datasource.createUser(token, secret, userId);
loadData();
};
};
}
UPDATE
OAuthService class is from Scribe
Token class is from Scribe
UserDataSource class is a DB Helper Class more here

Google App Engine Unable to Send GCM Token

I am working with Google App Engine .I want to Send GCM toke(RegID) to App Engine Server.But Problem is that when i pass RegId as a parameter Nothing happen and when i pass normal string like"abcefghi" the string is passed to server
my code is shown below
public class SendInstanceidAsync extends AsyncTask<Void, Void, UpdateInstanceIdResult> {
private UpdateinstanceidAPI updateinstanceidAPIservice;
private String token;
private String scholarNumber;
private String schoolId;
private RegistrationIntentService registrationIntentService;
public SendInstanceidAsync(RegistrationIntentService registrationIntentService, String token, String schoolId, String scholarNumber) {
this.token = token;
this.scholarNumber = scholarNumber;
this.schoolId = schoolId;
this.registrationIntentService = registrationIntentService;
}
#Override
protected UpdateInstanceIdResult doInBackground(Void... params) {
UpdateInstanceIdResult updateInstanceIdResult = new UpdateInstanceIdResult();
if (updateinstanceidAPIservice == null) {
UpdateinstanceidAPI.Builder builder = new UpdateinstanceidAPI.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
.setRootUrl("http://xxx.xxx.x.x:xxxx/_xx/api/")
.setGoogleClientRequestInitializer(new UpdateinstanceidAPIRequestInitializer() {
#Override
protected void initializeUpdateinstanceidAPIRequest(UpdateinstanceidAPIRequest<?> request) throws IOException {
request.setDisableGZipContent(true);
}
});
updateinstanceidAPIservice = builder.build();
}
try {
updateInstanceIdResult = updateinstanceidAPIservice.updateInstanceID(schoolId, scholarNumber, token).execute();
} catch (IOException e) {
e.printStackTrace();
}
return updateInstanceIdResult;
}

login issue using twitter api in android

what is the procedure to login throw twitter api1.1.
i have used old api that will show me twitter connection failed because of api 1 is deprecated.
private final TwDialogListener mTwLoginDialogListener = new TwDialogListener()
{
public void onComplete(String value)
{
getTwitterDetail();
}
public void onError(String value) {
Toast.makeText(LoginActivity.this, "Twitter connection failed", Toast.LENGTH_LONG).show();
}
};
LOG
{"errors": [{"message": "The Twitter REST API v1 is no longer active.
Please migrate to API v1.1. https://dev.twitter.com/docs/api/1.1/overview.", "code": 68}]}
As you see from error log API v.1 is no longer active and everybody must migrate to v1.1. In API v1.1. you must log in via OAUTH to get connected. So you also have to register your app on dev.twitter.com.
You can find below example here
public class Main extends Activity{
public static final String TAG = Main.class.getSimpleName();
public static final String TWITTER_OAUTH_REQUEST_TOKEN_ENDPOINT = "..."; //cannot share more then 2 lins, sorry
public static final String TWITTER_OAUTH_ACCESS_TOKEN_ENDPOINT = "...";
public static final String TWITTER_OAUTH_AUTHORIZE_ENDPOINT = "...";
private CommonsHttpOAuthProvider commonsHttpOAuthProvider;
private CommonsHttpOAuthConsumer commonsHttpOAuthConsumer;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
commonsHttpOAuthProvider = new CommonsHttpOAuthProvider(TWITTER_OAUTH_REQUEST_TOKEN_ENDPOINT,
TWITTER_OAUTH_ACCESS_TOKEN_ENDPOINT, TWITTER_OAUTH_AUTHORIZE_ENDPOINT);
commonsHttpOAuthConsumer = new CommonsHttpOAuthConsumer(getString(R.string.twitter_oauth_consumer_key),
getString(R.string.twitter_oauth_consumer_secret));
commonsHttpOAuthProvider.setOAuth10a(true);
TwDialog dialog = new TwDialog(this, commonsHttpOAuthProvider, commonsHttpOAuthConsumer,
dialogListener, R.drawable.android);
dialog.show();
}
private Twitter.DialogListener dialogListener = new Twitter.DialogListener() {
public void onComplete(Bundle values) {
String secretToken = values.getString("secret_token");
Log.i(TAG,"secret_token=" + secretToken);
String accessToken = values.getString("access_token");
Log.i(TAG,"access_token=" + accessToken);
new Tweeter(accessToken,secretToken).tweet(
"Tweet from sample Android OAuth app. unique code: " + System.currentTimeMillis());
}
public void onTwitterError(TwitterError e) { Log.e(TAG,"onTwitterError called for TwitterDialog",
new Exception(e)); }
public void onError(DialogError e) { Log.e(TAG,"onError called for TwitterDialog", new Exception(e)); }
public void onCancel() { Log.e(TAG,"onCancel"); }
};
public static final Pattern ID_PATTERN = Pattern.compile(".*?\"id_str\":\"(\\d*)\".*");
public static final Pattern SCREEN_NAME_PATTERN = Pattern.compile(".*?\"screen_name\":\"([^\"]*).*");
public class Tweeter {
protected CommonsHttpOAuthConsumer oAuthConsumer;
public Tweeter(String accessToken, String secretToken) {
oAuthConsumer = new CommonsHttpOAuthConsumer(getString(R.string.twitter_oauth_consumer_key),
getString(R.string.twitter_oauth_consumer_secret));
oAuthConsumer.setTokenWithSecret(accessToken, secretToken);
}
public boolean tweet(String message) {
if (message == null && message.length() > 140) {
throw new IllegalArgumentException("message cannot be null and must be less than 140 chars");
}
// create a request that requires authentication
try {
HttpClient httpClient = new DefaultHttpClient();
Uri.Builder builder = new Uri.Builder();
builder.appendPath("statuses").appendPath("update.json")
.appendQueryParameter("status", message);
Uri man = builder.build();
HttpPost post = new HttpPost("http://twitter.com" + man.toString());
oAuthConsumer.sign(post);
HttpResponse resp = httpClient.execute(post);
String jsonResponseStr = convertStreamToString(resp.getEntity().getContent());
Log.i(TAG,"response: " + jsonResponseStr);
String id = getFirstMatch(ID_PATTERN,jsonResponseStr);
Log.i(TAG,"id: " + id);
String screenName = getFirstMatch(SCREEN_NAME_PATTERN,jsonResponseStr);
Log.i(TAG,"screen name: " + screenName);
final String url = MessageFormat.format("https://twitter.com/#!/{0}/status/{1}",screenName,id);
Log.i(TAG,"url: " + url);
Runnable runnable = new Runnable() {
public void run() {
((TextView)Main.this.findViewById(R.id.textView)).setText("Tweeted: " + url);
}
};
Main.this.runOnUiThread(runnable);
return resp.getStatusLine().getStatusCode() == 200;
} catch (Exception e) {
Log.e(TAG,"trying to tweet: " + message, e);
return false;
}
}
}
public static String convertStreamToString(java.io.InputStream is) {
try {
return new java.util.Scanner(is).useDelimiter("\\A").next();
} catch (java.util.NoSuchElementException e) {
return "";
}
}
public static String getFirstMatch(Pattern pattern, String str){
Matcher matcher = pattern.matcher(str);
if(matcher.matches()){
return matcher.group(1);
}
return null;
}

Upgrage Twitter login to use Twitter API 1.1

I use this sample to login Twitter, post status and photo. I used it for a long time. Now Twitter requires upgrading from Twitter API 1.0 to Twitter API 1.1. What do I have to do to upgrade it? I tried to replace the old lib with this lib and there is no problem so far but I'm scared of I didn't do the change completely.
You must log in via OAUTH (https://dev.twitter.com/docs/auth/using-oauth) to get connected. So you also have to register your app on dev.twitter.com.
You can find below example here https://github.com/browep/Android-OAuth-Twitter-Example.
public class Main extends Activity{
public static final String TAG = Main.class.getSimpleName();
public static final String TWITTER_OAUTH_REQUEST_TOKEN_ENDPOINT = "..."; //cannot share more then 2 lins, sorry
public static final String TWITTER_OAUTH_ACCESS_TOKEN_ENDPOINT = "...";
public static final String TWITTER_OAUTH_AUTHORIZE_ENDPOINT = "...";
private CommonsHttpOAuthProvider commonsHttpOAuthProvider;
private CommonsHttpOAuthConsumer commonsHttpOAuthConsumer;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
commonsHttpOAuthProvider = new CommonsHttpOAuthProvider(TWITTER_OAUTH_REQUEST_TOKEN_ENDPOINT,
TWITTER_OAUTH_ACCESS_TOKEN_ENDPOINT, TWITTER_OAUTH_AUTHORIZE_ENDPOINT);
commonsHttpOAuthConsumer = new CommonsHttpOAuthConsumer(getString(R.string.twitter_oauth_consumer_key),
getString(R.string.twitter_oauth_consumer_secret));
commonsHttpOAuthProvider.setOAuth10a(true);
TwDialog dialog = new TwDialog(this, commonsHttpOAuthProvider, commonsHttpOAuthConsumer,
dialogListener, R.drawable.android);
dialog.show();
}
private Twitter.DialogListener dialogListener = new Twitter.DialogListener() {
public void onComplete(Bundle values) {
String secretToken = values.getString("secret_token");
Log.i(TAG,"secret_token=" + secretToken);
String accessToken = values.getString("access_token");
Log.i(TAG,"access_token=" + accessToken);
new Tweeter(accessToken,secretToken).tweet(
"Tweet from sample Android OAuth app. unique code: " + System.currentTimeMillis());
}
public void onTwitterError(TwitterError e) { Log.e(TAG,"onTwitterError called for TwitterDialog",
new Exception(e)); }
public void onError(DialogError e) { Log.e(TAG,"onError called for TwitterDialog", new Exception(e)); }
public void onCancel() { Log.e(TAG,"onCancel"); }
};
public static final Pattern ID_PATTERN = Pattern.compile(".*?\"id_str\":\"(\\d*)\".*");
public static final Pattern SCREEN_NAME_PATTERN = Pattern.compile(".*?\"screen_name\":\"([^\"]*).*");
public class Tweeter {
protected CommonsHttpOAuthConsumer oAuthConsumer;
public Tweeter(String accessToken, String secretToken) {
oAuthConsumer = new CommonsHttpOAuthConsumer(getString(R.string.twitter_oauth_consumer_key),
getString(R.string.twitter_oauth_consumer_secret));
oAuthConsumer.setTokenWithSecret(accessToken, secretToken);
}
public boolean tweet(String message) {
if (message == null && message.length() > 140) {
throw new IllegalArgumentException("message cannot be null and must be less than 140 chars");
}
// create a request that requires authentication
try {
HttpClient httpClient = new DefaultHttpClient();
Uri.Builder builder = new Uri.Builder();
builder.appendPath("statuses").appendPath("update.json")
.appendQueryParameter("status", message);
Uri man = builder.build();
HttpPost post = new HttpPost("http://twitter.com" + man.toString());
oAuthConsumer.sign(post);
HttpResponse resp = httpClient.execute(post);
String jsonResponseStr = convertStreamToString(resp.getEntity().getContent());
Log.i(TAG,"response: " + jsonResponseStr);
String id = getFirstMatch(ID_PATTERN,jsonResponseStr);
Log.i(TAG,"id: " + id);
String screenName = getFirstMatch(SCREEN_NAME_PATTERN,jsonResponseStr);
Log.i(TAG,"screen name: " + screenName);
final String url = MessageFormat.format("https://twitter.com/#!/{0}/status/{1}",screenName,id);
Log.i(TAG,"url: " + url);
Runnable runnable = new Runnable() {
public void run() {
((TextView)Main.this.findViewById(R.id.textView)).setText("Tweeted: " + url);
}
};
Main.this.runOnUiThread(runnable);
return resp.getStatusLine().getStatusCode() == 200;
} catch (Exception e) {
Log.e(TAG,"trying to tweet: " + message, e);
return false;
}
}
}
public static String convertStreamToString(java.io.InputStream is) {
try {
return new java.util.Scanner(is).useDelimiter("\\A").next();
} catch (java.util.NoSuchElementException e) {
return "";
}
}
public static String getFirstMatch(Pattern pattern, String str){
Matcher matcher = pattern.matcher(str);
if(matcher.matches()){
return matcher.group(1);
}
return null;
}

Twitter Integration : The request is understood, but it has been refused. This code is used when requests are being denied due to update limits [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Twitter API rate limits for posting updates
I have Integrated twitter in my application by Integrating "httpclient-4.0.1.jar", "signpost-commonhttp4-1.2.1.1.jar","signpost-core-1.2.1.1.jar", "twitter4j-core-2.1.11.jar" files..
The code is:
public class AndroidTwitterSample extends Activity {
private SharedPreferences prefs;
private final Handler mTwitterHandler = new Handler();
private TextView loginStatus;
String message="Hii";
final Runnable mUpdateTwitterNotification = new Runnable() {
public void run() {
Toast.makeText(getBaseContext(), "Tweet sent !", Toast.LENGTH_LONG).show();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
loginStatus = (TextView)findViewById(R.id.login_status);
Button tweet = (Button) findViewById(R.id.btn_tweet);
Button clearCredentials = (Button) findViewById(R.id.btn_clear_credentials);
tweet.setOnClickListener(new View.OnClickListener() {
/**
* Send a tweet. If the user hasn't authenticated to Tweeter yet, he'll be redirected via a browser
* to the twitter login page. Once the user authenticated, he'll authorize the Android application to send
* tweets on the users behalf.
*/
public void onClick(View v) {
if (TwitterUtils.isAuthenticated(prefs)) {
sendTweet();
} else {
Intent i = new Intent(getApplicationContext(), PrepareRequestTokenActivity.class);
i.putExtra("tweet_msg",getTweetMsg());
startActivity(i);
}
}
});
clearCredentials.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
clearCredentials();
updateLoginStatus();
}
});
}
#Override
protected void onResume() {
super.onResume();
updateLoginStatus();
}
public void updateLoginStatus() {
loginStatus.setText("Logged into Twitter : " + TwitterUtils.isAuthenticated(prefs));
}
private String getTweetMsg() {
return message;
}
public void sendTweet() {
Thread t = new Thread() {
public void run() {
try {
TwitterUtils.sendTweet(prefs,getTweetMsg());
mTwitterHandler.post(mUpdateTwitterNotification);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
t.start();
}
private void clearCredentials() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
final Editor edit = prefs.edit();
edit.remove(OAuth.OAUTH_TOKEN);
edit.remove(OAuth.OAUTH_TOKEN_SECRET);
edit.commit();
}
}
The Constants class:
public class Constants {
public static final String CONSUMER_KEY = "<key>";
public static final String CONSUMER_SECRET= "<secret>";
public static final String REQUEST_URL = "https://api.twitter.com/oauth/request_token";
public static final String ACCESS_URL = "https://api.twitter.com/oauth/access_token";
public static final String AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize";
public static final String OAUTH_CALLBACK_SCHEME = "x-oauthflow-twitter";
public static final String OAUTH_CALLBACK_HOST = "callback";
public static final String OAUTH_CALLBACK_URL = OAUTH_CALLBACK_SCHEME + "://" + OAUTH_CALLBACK_HOST;
}
The OAuthRequestToken class:
public class OAuthRequestTokenTask extends AsyncTask<Void, Void, Void> {
final String TAG = getClass().getName();
private Context context;
private OAuthProvider provider;
private OAuthConsumer consumer;
/**
*
* We pass the OAuth consumer and provider.
*
* #param context
* Required to be able to start the intent to launch the browser.
* #param provider
* The OAuthProvider object
* #param consumer
* The OAuthConsumer object
*/
public OAuthRequestTokenTask(Context context,OAuthConsumer consumer,OAuthProvider provider) {
this.context = context;
this.consumer = consumer;
this.provider = provider;
}
/**
*
* Retrieve the OAuth Request Token and present a browser to the user to authorize the token.
*
*/
#Override
protected Void doInBackground(Void... params) {
try {
Log.i(TAG, "Retrieving request token from Google servers");
final String url = provider.retrieveRequestToken(consumer, Constants.OAUTH_CALLBACK_URL);
Log.i(TAG, "Popping a browser with the authorize URL : " + url);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_FROM_BACKGROUND);
context.startActivity(intent);
} catch (Exception e) {
Log.e(TAG, "Error during OAUth retrieve request token", e);
}
return null;
}
}
PrepareRequestTokenActivity:
public class PrepareRequestTokenActivity extends Activity {
final String TAG = getClass().getName();
private OAuthConsumer consumer;
private OAuthProvider provider;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
this.consumer = new CommonsHttpOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
this.provider = new CommonsHttpOAuthProvider(Constants.REQUEST_URL,Constants.ACCESS_URL,Constants.AUTHORIZE_URL);
} catch (Exception e) {
Log.e(TAG, "Error creating consumer / provider",e);
}
Log.i(TAG, "Starting task to retrieve request token.");
new OAuthRequestTokenTask(this,consumer,provider).execute();
}
/**
* Called when the OAuthRequestTokenTask finishes (user has authorized the request token).
* The callback URL will be intercepted here.
*/
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
final Uri uri = intent.getData();
if (uri != null && uri.getScheme().equals(Constants.OAUTH_CALLBACK_SCHEME)) {
Log.i(TAG, "Callback received : " + uri);
Log.i(TAG, "Retrieving Access Token");
new RetrieveAccessTokenTask(this,consumer,provider,prefs).execute(uri);
finish();
}
}
public class RetrieveAccessTokenTask extends AsyncTask<Uri, Void, Void> {
private Context context;
private OAuthProvider provider;
private OAuthConsumer consumer;
private SharedPreferences prefs;
public RetrieveAccessTokenTask(Context context, OAuthConsumer consumer,OAuthProvider provider, SharedPreferences prefs) {
this.context = context;
this.consumer = consumer;
this.provider = provider;
this.prefs=prefs;
}
/**
* Retrieve the oauth_verifier, and store the oauth and oauth_token_secret
* for future API calls.
*/
#Override
protected Void doInBackground(Uri...params) {
final Uri uri = params[0];
final String oauth_verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
try {
provider.retrieveAccessToken(consumer, oauth_verifier);
final Editor edit = prefs.edit();
edit.putString(OAuth.OAUTH_TOKEN, consumer.getToken());
edit.putString(OAuth.OAUTH_TOKEN_SECRET, consumer.getTokenSecret());
edit.commit();
String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");
consumer.setTokenWithSecret(token, secret);
context.startActivity(new Intent(context,AndroidTwitterSample.class));
executeAfterAccessTokenRetrieval();
Log.i(TAG, "OAuth - Access Token Retrieved");
} catch (Exception e) {
Log.e(TAG, "OAuth - Access Token Retrieval Error", e);
}
return null;
}
private void executeAfterAccessTokenRetrieval() {
String msg = getIntent().getExtras().getString("tweet_msg");
try {
TwitterUtils.sendTweet(prefs, msg);
} catch (Exception e) {
Log.e(TAG, "OAuth - Error sending to Twitter", e);
}
}
}
}
TwitterUtils:
public class TwitterUtils {
public static boolean isAuthenticated(SharedPreferences prefs) {
String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");
AccessToken a = new AccessToken(token,secret);
Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
twitter.setOAuthAccessToken(a);
try {
twitter.getAccountSettings();
return true;
} catch (TwitterException e) {
return false;
}
}
public static void sendTweet(SharedPreferences prefs,String msg) throws Exception {
String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");
AccessToken a = new AccessToken(token,secret);
Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
twitter.setOAuthAccessToken(a);
twitter.updateStatus(msg);
}
}
The problem is after 2 tweets, It is giving me an exception:
W/System.err(5104): 403:The request is understood, but it has been refused. An accompanying error message will explain why. This code is used when requests are being denied due to update limits (http://support.twitter.com/forums/10711/entries/15364).
W/System.err(5104): error - Status is a duplicate.
W/System.err(5104): request - /1/statuses/update.json
W/System.err(5104): Relevant discussions can be on the Internet at:
W/System.err(5104): http://www.google.co.jp/search?q=15bb6564 or
W/System.err(5104): http://www.google.co.jp/search?q=010f3e5b
W/System.err(5104): TwitterException{exceptionCode=[15bb6564-010f3e5b], statusCode=403, retryAfter=0, rateLimitStatus=null, version=2.1.11}
W/System.err(5104): at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:199)
W/System.err(5104): at twitter4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:75)
W/System.err(5104): at twitter4j.internal.http.HttpClientWrapper.post(HttpClientWrapper.java:112)
W/System.err(5104): at twitter4j.Twitter.updateStatus(Twitter.java:593)
W/System.err(5104): at com.ecs.android.sample.twitter.TwitterUtils.sendTweet(TwitterUtils.java:38)
W/System.err(5104): at com.ecs.android.sample.twitter.AndroidTwitterSample$4.run(AndroidTwitterSample.java:84)
From your error message:
error - Status is a duplicate.
It means that you cannot tweet the same message twice.
If you have tweeted the message HI then you cannot tweet it again( at least on that day- not sure). You will get the Status is a duplicate error

Categories

Resources