Getting 403 forbidden when using Twitter Fabric to get user_timeline - android

I've been trying to implement Fabric to get a list of the 5 latest tweet from a user. It worked great for a few hours and then it stopped working. I would like to do this without having the user log in, and as far as I can tell the API allows guest-logins to read tweets, but maybe this has a greater effect on the Rate Limit?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
Fabric.with(this, new Twitter(authConfig), new Crashlytics());
TwitterCore.getInstance().logInGuest(new Callback() {
#Override
public void success(Result result) {
AppSession session = (AppSession) result.data;
getTweets();
}
#Override
public void failure(TwitterException exception) {
// unable to get an AppSession with guest auth
}
});
}
public void getTweets() {
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient();
StatusesService statusesService = twitterApiClient.getStatusesService();
statusesService.userTimeline([USERID], null, 5, null, null, null, true, null, false, new Callback<List<Tweet>>() {
#Override
public void success(Result <List<Tweet>> result) {
for(Tweet Tweet : result.data) {
tweetList.add(Tweet.text);
}
createListView();
}
public void failure(TwitterException exception) {
Log.e("Failure", exception.toString());
exception.printStackTrace();
}
});
}
When I don't get the 403 everything works perfectly and my list gets populated.
Now, it's entirely possible that there is just something wrong my code that gets me rate limit blacklisted? Otherwise; do I need have the user log in just to show them 5 tweets? Or should I implement some sort of serverside-cache?
Thankful for any tips/help.

I think I might have it figured out. Looks like you have to save the session from the success method in the logInGuest callback and then pass that to getApiClient. Here's some code that's working for me so far:
private TweetViewFetchAdapter adapter;
...
adapter = new TweetViewFetchAdapter<CompactTweetView>(getActivity());
...
TwitterCore.getInstance().logInGuest( new Callback<AppSession>() {
#Override
public void success(Result<AppSession> appSessionResult) {
AppSession session = appSessionResult.data;
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient(session);
twitterApiClient.getStatusesService().userTimeline(null, "RadioOkinawa864", 10, null, null, false, false, false, true, new Callback<List<Tweet>>() {
#Override
public void success(Result<List<Tweet>> listResult) {
adapter.setTweets(listResult.data);
}
#Override
public void failure(TwitterException e) {
Toast.makeText(getActivity().getApplicationContext(), "Could not retrieve tweets", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
});
}
#Override
public void failure(TwitterException e) {
Toast.makeText(getActivity().getApplicationContext(), "Could not get guest Twitter session", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
});

When using logInGuest, be aware that guest AppSessions will expire after some time. Your application must handle expiration TwitterExceptions and request another guest AppSession. For example,
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient(guestAppSession);
twitterApiClient.getSearchService().tweets("#fabric", null, null, null, null, 50, null, null, null, true, new Callback<Search>() {
#Override
public void success(Result<Search> result) {
// use result tweets
}
#Override
public void failure(TwitterException exception) {
final TwitterApiException apiException = (TwitterApiException) exception;
final int errorCode = apiException.getErrorCode();
if (errorCode == TwitterApiConstants.Errors.APP_AUTH_ERROR_CODE || errorCode == TwitterApiConstants.Errors.GUEST_AUTH_ERROR_CODE) {
// request new guest AppSession (i.e. logInGuest)
// optionally retry
}
}
});
Note that AppSessions may only be used to make API requests that do not require a user context. For example, you cannot Tweet with an AppSession. You can get a user's timeline of public Tweets. See TwitterKit Android REST API docs.
Finally, if you are using the TweetUtils.loadTweet or TweetUtils.loadTweets helpers from the TweetUi kit of the Twitter kit group, setting up guest auth and handling expiration is performed automatically, you need not call logInGuest yourself.

In my case the api returned 403 forbidden with the following message Your app may not allow guest auth. Please talk to us regarding upgrading your consumer key.
Be sure your are not in the same status.

Related

How to get user details from twitter API in android application

I am doing an android app with TwitterLogin Integration using Twitter Api. Here I am not using any twitter 4j and fabric . I am able to get Twitter user name but unable to get Email Id. searched more for this issue, but got nothing with twitter api.
I followed this twitterAPI to login
and this is my code
twitterLoginButton.setCallback(new Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> result) {
System.out.println("=======twitterlogin success=======");
String username=result.data.getUserName();
getUsertwitteremail();
}
#Override
public void failure(TwitterException exception) {
System.out.println("=======twitterlogin failure==========");
}
});
please someone help me to get the details including email.
First of all make sure Request email addresses from users is checked for your Twitter app
Check out the code below and get the email
mTwitterAuthClient.authorize(this, new com.twitter.sdk.android.core.Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> twitterSessionResult) {
TwitterSession session = TwitterCore.getInstance().getSessionManager().getActiveSession();
TwitterAuthToken authToken = session.getAuthToken();
String token = authToken.token;
String secret = authToken.secret;
long userId = session.getUserId();
String userNa = session.getUserName();
Log.d("twitter check", userNa + " " + secret);
mTwitterAuthClient.requestEmail(session, new Callback<String>() {
#Override
public void success(Result<String> result) {
Log.d("email", result.data);
// Do something with the result, which provides the email address
}
#Override
public void failure(TwitterException exception) {
// Do something on failure
}
});
}
#Override
public void failure(TwitterException e) {
e.printStackTrace();
}
});
please enable permissions for email access form your twitter app console.
from here
https://apps.twitter.com/app/14057942/permissions

Tweeting from Android application without Twitter app

I'm working on an Android application that allows users to share an article via Facebook and/or Twitter. Facebook share works well using ShareDialog, which opens up Facebook share dialog in my application.
The problem I'm having is with posting to Twitter. If the user has a Twitter app installed, share works perfectly. When there is no Twitter app installed on the device, then the Twitter share page is opened in the default browser and user never gets returned to my application after tweeting, which is kind of a bad user experience.
My code for tweet posting is:
Intent intent = new TweetComposer.Builder(context).text("Tweet text.").createIntent();
startActivityForResult(intent, SHARE_ACTION_TWITTER);
I have also tried this:
TweetComposer.Builder builder = new TweetComposer.Builder(this).text("Tweet text.");
builder.show();
Is there a way to get a dialog in my application (similar to Facebook share behavior) when the user does not have the Twitter app installed?
Additionally, for statistics, I would like to know if the user has successfully posted a tweet. How can this be achieved with Fabric Twitter API if user does not have Twitter app installed? Should I use a different API?
The solution was to create a custom webview for tweeting. It doesn't even require the Fabric Twitter API.
Most important part is to create a webview activity:
public class TweetCustomWebView extends AppCompatActivity {
android.webkit.WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview_activity);
Bundle extras = getIntent().getExtras();
if (extras != null) {
final String stringToShow = extras.getString("tweettext");
webView = (android.webkit.WebView) findViewById(R.id.wv);
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(android.webkit.WebView view, String url) {
if (url.contains("latest_status_id=")) {
// Twitted
setResult(Activity.RESULT_OK, new Intent());
TweetCustomWebView.this.finish();
}
view.loadUrl(url);
return true;
}
public void onPageFinished(android.webkit.WebView view, String url) {
// Finished loading url
}
public void onReceivedError(android.webkit.WebView view, int errorCode, String description, String failingUrl) {
Log.e("", "Error: " + description);
setResult(Activity.RESULT_CANCELED, new Intent());
}
});
webView.loadUrl("https://twitter.com/intent/tweet?text=" + stringToShow);
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
setResult(Activity.RESULT_CANCELED, new Intent());
}
}
And a layout like this:
<WebView android:layout_width="match_parent" android:layout_height="match_parent" android:id="#+id/wv"/>
In the AndroidManifest.xml we must add the activity for our webview inside the <application> tag:
<activity android:name=".TweetCustomWebView" />
Last step is to call our vebview when user taps Share on Twitter button:
Intent intent = new Intent(MainActivity.this, TweetCustomWebView.class);
intent.putExtra("tweettext", "Text to tweet");
startActivityForResult(intent, 100);
That should be it. I hope this will help someone.
use below code to post status to twitter.it use's twitter's rest api calls:
i am sharing successfully from my app. it doesn't require twitter app to be installed.
TwitterAuthClient mTwitterAuthClient = new TwitterAuthClient();
mTwitterAuthClient.authorize(this, new Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> result) {
TwitterSession session = result.data;
twitterApiClient = TwitterCore.getInstance().getApiClient(session);
statusesService = twitterApiClient.getStatusesService();
postToTwitter("here goes your share message to post status");
}
}
public void postToTwitter(String Message) {
String message;
StatusesService statusesService = twitterApiClient.getStatusesService();
statusesService.update(message, null, null, null, null, null, null, null, mediaId, new Callback<Tweet>() {
#Override
public void success(Result<Tweet> result) {
//handle success case
}
#Override
public void failure(TwitterException exception) {
//handle failure case
}
});
}
I guess the correct answer is using Update Status API call.
I'm using the latest Twitter SDK version: com.twitter.sdk.android:twitter:3.1.1
public void publishTwitter(final String message) {
final TwitterApiClient apiClient = TwitterCore.getInstance().getApiClient();
final StatusesService statusesService = apiClient.getStatusesService();
final Call<Tweet> update = statusesService.update(message, null, null, null, null, null, null, null, null);
update.enqueue(new com.twitter.sdk.android.core.Callback<Tweet>() {
#Override
public void success(Result<Tweet> result) {
Log.d("TweetTest", "Tweet generated");
}
#Override
public void failure(TwitterException exception) {
Log.e("TweetTest", exception.getLocalizedMessage());
}
});
}
NOTE
The user must be authenticated before calling this API call.
For further details, check this post on Twitter Dev Forum.
Best regards

Unable to get Publish Permission With Test User Facebook Android

I want to publish post to user's wall. I know Facebook only allows tester and developers to post on wall. I have already added user to tester list. When I try to get publish permission, it says that user has already granted permission (as shown in screenshot) and returns. I am not able to get permission or post on wall. Moreover, callback's any method is not called as well.
CODE
I have followed code from Facebook Example RPSSample.
//Publish to wall
public void publishResult() {
registerPublishPermissionCallback();
if (canPublish()) { //see definition below
ShareLinkContent content = new ShareLinkContent.Builder()
.setContentUrl(Uri.parse(urlToPost))
.build();
ShareApi.share(content, new FacebookCallback<Sharer.Result>() {
#Override
public void onSuccess(Sharer.Result result) {
callback.didShareOnFacebookSuccessfully();
}
#Override
public void onCancel() {
// This should not happen
}
#Override
public void onError(FacebookException error) {
showToast(error.getMessage());
}
});
}
}
//check if user has permission or not
private boolean canPublish() {
final AccessToken accessToken = AccessToken.getCurrentAccessToken();
if (accessToken != null) {
if (accessToken.getPermissions().contains(AppConstants.ADDITIONAL_PERMISSIONS)) {
// if we already have publish permissions, then go ahead and publish
return true;
} else {
// otherwise we ask the user if they'd like to publish to facebook
new AlertDialog.Builder(activity)
.setTitle(R.string.share_with_friends_title)
.setMessage(urlToPost)
.setPositiveButton(R.string.share_with_friends_yes, canPublishClickListener)
.setNegativeButton(R.string.share_with_friends_no, dontPublishClickListener)
.show();
return false;
}
}
return false;
}
//If user allows, ask Facebook to grant publish_action permission
private DialogInterface.OnClickListener canPublishClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if (AccessToken.getCurrentAccessToken() != null) {
// if they choose to publish, then we request for publish permissions
LoginManager.getInstance()
.setDefaultAudience(DefaultAudience.FRIENDS)
.logInWithPublishPermissions(activity,
Arrays.asList(AppConstants.ADDITIONAL_PERMISSIONS));
}
}
};
//Callback - Any of the method doesn't call.
private void registerPublishPermissionCallback() {
LoginManager.getInstance().registerCallback(
callbackManager,
new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
AccessToken accessToken = AccessToken.getCurrentAccessToken();
if (accessToken.getPermissions().contains(AppConstants.ADDITIONAL_PERMISSIONS)) {
publishResult();
} else {
handleError("Not enough permissions to publish");
}
}
#Override
public void onCancel() {
}
#Override
public void onError(FacebookException exception) {
handleError(exception.getMessage());
}
private void handleError(String errorMessage) {
// this means the user did not grant us write permissions, so
// we don't do implicit publishes
showToast(errorMessage);
}
}
);
}
My app is live on console. Please guide what is requirement of Facebook to get publish permission with test user? Thanks.
Use below code to check if permission is Granted or not.
String url = "/" + "(userFbID)" + "/permissions";
new GraphRequest(AccessToken.getCurrentAccessToken(), url, null,
HttpMethod.GET, new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
try {
JSONObject json = new JSONObject(
response.getRawResponse());
JSONArray data = json.getJSONArray("data");
boolean isPermitted = false;
for (int i = 0; i < data.length(); i++) {
if (data.getJSONObject(i)
.getString("permission")
.equals("publish_actions")) {
isPermitted = true;
String status = data.getJSONObject(i)
.getString("status");
if (status.equals("granted")) {
publishResult()
} else {
LoginFacebook();
}
break;
}
}
if (!isPermitted) {
LoginFacebook();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).executeAsync();
replace user's fb id on place of (userFbID).
If permission is not granted then use this function to ask user for that permission.
private void LoginFacebook() {
loginManager = LoginManager.getInstance();
loginManager.logInWithPublishPermissions(this,
Arrays.asList("publish_actions"));
loginManager.registerCallback(callbackManager,
new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
publishResult()
}
#Override
public void onError(FacebookException error) {
}
#Override
public void onCancel() {
}
});
}
Finally able to solve the problem. There was no issue in code. It was some setting / permission issue with Facebook app. These are steps I followed:
Remove the user from Test role section in your Facebook Developer Console.
Revoke App's Access by logging into that user's account. Go to Settings > Apps. Remove the app from there. You need to wait 10-15 min, since it takes time from Facebook side to revoke access completely.
Make your Facebook App in Sandbox mode (you need to do this to perform publish testing).
Login your android app using any Facebook account other than app admin. It should throw error that app is in development mode.
Add user as Tester in the Facebook Console App. That user may need to approve pending request at his side.
Login from that user account. Facebook will now ask you to provide basic information access to the app. After that you can test publishing. You will be able to post on the user's wall successfully.
Hope this helps someone!

Get list of tweets in user time line using Fabric Android

I use the following code:
UserTimeline userTimeline = new UserTimeline.Builder().screenName("ZainAlabdin878").build();
final TweetTimelineListAdapter adapter = new TweetTimelineListAdapter(MainActivity.this, userTimeline);
System.out.println(adapter.getCount()+"");
I get the output 0 although I have tweets.
Am I doing something wrong?
what I am trying to achieve is to get a list of tweets of a certain user. I'm using android studio and plugin.
*my goal is not to display the list but rather to get a List
many thanks.
final TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
Fabric.with(context, new Twitter(authConfig), new TweetUi());
TwitterCore.getInstance().logInGuest(new Callback<AppSession>() {
#Override
public void success(Result<AppSession> result) {
AppSession session = result.data;
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient(session);
twitterApiClient.getStatusesService().userTimeline(tweetId, screenName, tweetCount, null, null, false, false, false, true, new Callback<List<Tweet>>() {
#Override
public void success(Result<List<Tweet>> listResult) {
for (Tweet tweet : listResult.data) {
// here you will get list
}
}
#Override
public void failure(TwitterException e) {
e.printStackTrace();
}
});
}
#Override
public void failure(TwitterException e) {
Log.e(TAG, "Load Tweet failure", e);
}
});
more details available here
Here's the code you'll need to actually fetch the Tweet objects:
ArrayList<Tweet> tweets = new ArrayList<>();
TwitterCore.getInstance().getApiClient(session).getStatusesService()
.userTimeline(null,
"screenname",
10 //the number of tweets we want to fetch,
null,
null,
null,
null,
null,
null,
new Callback<List<Tweet>>() {
#Override
public void success(Result<List<Tweet>> result) {
for (Tweet t : result.data) {
tweets.add(t);
android.util.Log.d("twittercommunity", "tweet is " + t.text);
}
}
#Override
public void failure(TwitterException exception) {
android.util.Log.d("twittercommunity", "exception " + exception);
}
});
You'll need to run this in a new Thread (not the UI Thread)
EDIT
*Technically you don't have to run this in a new thread because it's asynchronous (someone please correct me here if I'm wrong). I know other Twitter API calls are async, so I'm assuming this one is too, although I cannot find where the actual call is happening in the Fabric source..*
Here's the full list of parameters for userTimeline() from the Fabric SDK
void userTimeline(#Query("user_id") Long var1, #Query("screen_name") String var2, #Query("count") Integer var3, #Query("since_id") Long var4, #Query("max_id") Long var5, #Query("trim_user") Boolean var6, #Query("exclude_replies") Boolean var7, #Query("contributor_details") Boolean var8, #Query("include_rts") Boolean var9, Callback<List<Tweet>> var10);

Android - Fabric.io Twitter REST API profile image / picture

Does anyone know if there is a way to pull a signed in users profile picture to be placed through the app, to maybe place it on the ActionBar as they navigate around?
hints, tips, examples, downloads all welcome :)
If you can help me, please assume I very little knowledge regarding anything outside basic Java!
Again, thanks people x
You can get a user's profile image by using /1.1/users/show.json. You can refer to REST API URLs for Twitter data.
By extending TwitterApiClient we can retrieve Twitter data from the URL.
class MyTwitterApiClient extends TwitterApiClient {
public MyTwitterApiClient(TwitterSession session) {
super(session);
}
public UsersService getUsersService() {
return getService(UsersService.class);
}
}
interface UsersService {
#GET("/1.1/users/show.json")
void show(#Query("user_id") Long userId,
#Query("screen_name") String screenName,
#Query("include_entities") Boolean includeEntities,
Callback<User> cb);
}
Next, get the UsersService and call its show method, passing in the defined query parameters. I defined the query parameters based on the ones that are documented.
new MyTwitterApiClient(session).getUsersService().show(12L, null, true,
new Callback<User>() {
#Override
public void success(Result<User> result) {
Log.d("twittercommunity", "user's profile url is "
+ result.data.profileImageUrlHttps);
}
#Override
public void failure(TwitterException exception) {
Log.d("twittercommunity", "exception is " + exception);
}
});
Courtesy: https://twittercommunity.com/t/android-get-user-profile-image/30579/2
This is how I got mine to work:
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient();
twitterApiClient.getAccountService().verifyCredentials(false,false, new Callback<User>() {
#Override
public void success(Result<User> userResult) {
String name = userResult.data.name;
String profilebannerurl = userResult.data.profileBannerUrl;
String profileurl = userResult.data.profileImageUrl;
}
#Override
public void failure(TwitterException e) {
}
});
I have place this piece of code within my LoginButton callback method:
loginButton.setCallback(new Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> result) { <insert here> }
I did it with a custom button and this is the code that is executed by it's onClick listener :
TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_API_KEY, TWITTER_API_SECRET);
Fabric.with(activity, new Twitter(authConfig));
TwitterCore.getInstance().getApiClient().getAccountService().verifyCredentials(false, false, new com.twitter.sdk.android.core.Callback<User>() {
#Override
public void success(Result<User> result) {
Log.d(TAG, "Twitter log in success");
String userName = result.data.screenName;
int userId = result.data.id;
String pictureUrl = result.data.profileImageUrl;
String coverUrl = result.data.profileBannerUrl;
}
#Override
public void failure(TwitterException e) {
Log.d(TAG, "Twitter log in error : " + e.getMessage());
}
});
I should ask the user to authorize access to your app and log him in if he accepts.

Categories

Resources