Tweeting from Android application without Twitter app - android

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

Related

How to get User's information after logging in Facebook app and authorized your app? [Android]

I'm using this for my Facebook log-in and sharing. I'm wondering if instead of opening a WebView that displays the log-in with Facebookis there a way when a User have already installed a Facebook app instead of opening the WebView it will opens the Facebook app? And when the User is already log-in in the Facebook App it will gets its credentials and log-in automatically in my app? I can't seem to find how to do this. Thank you in advantage.
Edit
I found out that my activityCode always return -1 instead of >= 0 that's why it always open the WebView instead of the app. And also found out that I need to enabled the Single Sign-On, I enabled the Single Sign-On but it still doesn't open the facebook app. Maybe it is because of FORCE_DIALOG_AUTH that always returns -1. I'm wondering if there is a default value instead of using FORCE_DIALOG_AUTH.
In solution on the FORCE_DIALOG_AUTH I used code below:
Instead of using
facebook.authorize(this, Constants.FACEBOOK_PERMISSIONS,
Facebook.FORCE_DIALOG_AUTH, new LoginDialogListener());
I used
facebook.authorize(this, Constants.FACEBOOK_PERMISSIONS, new LoginDialogListener());
where in my Facebook.java
public void authorize(Activity activity, String[] permissions,
final DialogListener listener) {
authorize(activity, permissions, DEFAULT_AUTH_ACTIVITY_CODE, listener);
}
Also it detects now if there is an Facebook app installed or not, but when there is an Facebook app installed it still doesn't display/open in Facebook app, it just load and goes back to my Activity nothing happens.
Update
I tried to log in without a user log-in in the Facebook app and that user is still not authorized to use my app, it opens the Facebook app log-in screen but after authorizing it, it doesn't get my log-in informations.
Here's my code in Facebook.java it same as it is
private boolean startSingleSignOn(Activity activity, String applicationId,
String[] permissions, int activityCode) {
boolean didSucceed = true;
Intent intent = new Intent();
intent.setClassName("com.facebook.katana",
"com.facebook.katana.ProxyAuth");
intent.putExtra("client_id", applicationId);
if (permissions.length > 0) {
intent.putExtra("scope", TextUtils.join(",", permissions));
}
// Verify that the application whose package name is
// com.facebook.katana.ProxyAuth
// has the expected FB app signature.
if (!validateActivityIntent(activity, intent)) {
return false;
}
mAuthActivity = activity;
mAuthPermissions = permissions;
mAuthActivityCode = activityCode;
try {
activity.startActivityForResult(intent, activityCode);
} catch (ActivityNotFoundException e) {
didSucceed = false;
}
return didSucceed;
}
In my activity that calls the authorizing and handles what to do after authorizing here's my code
private void setFacebookConnection() {
// progressBar.setVisibility(View.VISIBLE);
facebook = new Facebook(Constants.FACEBOOK_APP_ID);
facebookAsyncRunner = new AsyncFacebookRunner(facebook);
// facebook.authorize(MerchantDetailsActivity.this, Constants.FACEBOOK_PERMISSIONS,
// Facebook.FORCE_DIALOG_AUTH, new LoginDialogListener());
facebook.authorize(MerchantDetailsActivity.this, Constants.FACEBOOK_PERMISSIONS, new LoginDialogListener());
}
private class LoginDialogListener implements Facebook.DialogListener {
public void onComplete(Bundle values) {
String token = facebook.getAccessToken();
long token_expires = facebook.getAccessExpires();
Log.d(TAG, "AccessToken: " + token);
Log.d(TAG, "AccessExpires: " + token_expires);
facebookSharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
facebookSharedPreferences.edit()
.putLong(Constants.FACEBOOK_ACCESS_EXPIRES, token_expires)
.commit();
facebookSharedPreferences.edit()
.putString(Constants.FACEBOOK_ACCESS_TOKEN, token).commit();
facebookAsyncRunner.request("me", new IDRequestListener());
shareFBPost();
}
It seems that when the user is already authorized it doesn't go inside my LoginDialogListener
If you will use this guide you will be able to open Facebook app for login
After implementing Facebook auth, initialize Facebook SDK in your Application class or in activity which uses Facebook login
// initialize facebook sdk and app events logger
FacebookSdk.sdkInitialize(getApplicationContext());
Then you can use the class below to login
public class FacebookAuth {
private static FacebookAuth instance;
private OnLoginDataReadyListener mResponseListener;
public static synchronized FacebookAuth getInstance() {
if (instance == null) {
instance = new FacebookAuth();
}
return instance;
}
/**
* Call if you want the user to login with his facebook account
* #param activity needed to initialize the Facebook LoginManager
* #param listener used to set the login listener
*/
public void facebookLogin(Activity activity, OnLoginDataReadyListener listener, CallbackManager callbackManager) {
mResponseListener = listener;
LoginManager.getInstance().logInWithReadPermissions(activity, Arrays.asList("public_profile", "user_friends", "email"));
LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
getUserData();
}
#Override
public void onCancel() {
if (mResponseListener != null) {
mResponseListener.onCanceled();
}
}
#Override
public void onError(FacebookException error) {
if (mResponseListener != null) {
mResponseListener.onCanceled();
}
}
});
}
/**
* Creates an Facebook Graph request witch will grab the user data
* such as name id and picture for now
*/
public void getUserData() {
GraphRequest request = GraphRequest.newMeRequest( AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
if (mResponseListener != null) {
mResponseListener.onLoginDataReady(object);
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "picture.height(200).width(200),cover,location,birthday,first_name,last_name,email,gender,name");
request.setParameters(parameters);
request.executeAsync();
}
public interface OnLoginDataReadyListener {
void onLoginDataReady(JSONObject facebookData);
void onCanceled();
}
}
Once you've implemented the above solution, în your activity create a CallbackManager
CallbackManager mCallbackManager = CallbackManager.Factory.create();
Then in button click listener you can login your user as following
FacebookAuth.getInstance().facebookLogin(activity, dataReadyListener, mCallbackManager);
And finally in onActivityResult()
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mCallbackManager.onActivityResult(requestCode, resultCode, data);
}
Hope this will help you ))
I use the latest Facebook SDK instead and follow these steps. It is important to add onActivityResult for Facebook login callbackManager.

Using facebook sdk 4.4.1. Want to get the number of invites sent by the app user using app invite dialog?

i want to calculate the number of person app user has invited from his friend list.
this is my code. in result i m getting null.
public void openDialogInvite(final Activity activity) {
String AppURl = "https://fb.me/659724450828700"; //Generated from //fb developers
//String previewImageUrl = " ";
sCallbackManager = CallbackManager.Factory.create();
if (AppInviteDialog.canShow()) {
AppInviteContent content = new AppInviteContent.Builder()
.setApplinkUrl(AppURl)
//.setPreviewImageUrl(previewImageUrl)
.build();
final AppInviteDialog appInviteDialog = new AppInviteDialog(activity);
appInviteDialog.registerCallback(sCallbackManager,
new FacebookCallback<AppInviteDialog.Result>() {
#Override
public void onSuccess(AppInviteDialog.Result result) {
Log.v("invitation", result.toString());
// setting parameters for request execution for both graph api request
}
#Override
public void onCancel() {
}
#Override
public void onError(FacebookException e) {
Log.d("Invitation", "Error Occured");
}
});
appInviteDialog.show(content);
}
thanks in advance.
It is is not possible, to get the list of invited friends of a user until unless ur app is not a game on canvas.

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.

Getting 403 forbidden when using Twitter Fabric to get user_timeline

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.

How to log in with other facebook account?

I'm follow this tutorial to make a small app to login and say hello + user name.
The issue is: I can only login using my account, but can't log in with other account.
This issue is happen with some sample code require login like HelloFacebookSample or Scrumptious.
The Logcat is not show any error.
So please help me to make it login with other account. Thanks in advance!
EDIT (SOLVED):
I just found the cause: My app is in Sandbox mode, just disable Sandbox mode solved problem. Thanks anyone for helps.
My code:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// start Facebook Login
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
// make request to the /me API
Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null) {
TextView welcome = (TextView) findViewById(R.id.welcome);
welcome.setText("Hello " + user.getName() + "!");
}
}
});
}
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}
}
Screenshot when login with my account: Show hello + my name (Nguyễn Việt Anh)
Screenshot when login with other account: White screen
You can login with different Facebook user id, after that:
Go to developers.facebook.com
choose Apps from Top
select wanted App from left side
select Edit App
disable sandbox mode
This is expected behavior. Essentially the login for facebook is SSO (single sign on) so there is a strong expectation that the user has only one account on their device.
I myself have tried to find a way to get the Facebook SDK to allow the user to sign on to a different account but it doesn't work.
It might be possible fudge it by clearing the caches perhaps but this wouldn't help users who are using the genuine facebook app on their phone.
What I did in the end was went to the web workflow as opposed to native app. I can recommend scribe for this task.
https://github.com/fernandezpablo85/scribe-java
If you do choose to use Scribe, this is my activity for loggin in.
public class FacebookScribeLogin extends FragmentActivity{
private static final String TAG = FacebookScribeLogin.class.getSimpleName();
private final static String CALLBACK = "http://localhost:3000/";
private WebView mWebView;
private ProgressDialog mProgressDialog;
private OAuthService mAuthService;
private SyncStatusUpdaterFragment mSyncStatusUpdaterFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
mWebView = (WebView) findViewById(R.id.webview);
new GetLoginPage().execute();
}
private class GetLoginPage extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... voids) {
//set up service and get request token as seen on scribe website
//https://github.com/fernandezpablo85/scribe-java/wiki/Getting-Started
mAuthService = new ServiceBuilder()
.provider(FacebookApi.class)
.apiKey(getString(R.string.facebook_api_key))
.apiSecret(getString(R.string.facebook_api_secret))
.scope("read_stream, publish_stream, manage_notifications, publish_actions, manage_pages")
.callback(CALLBACK)
.build();
return mAuthService.getAuthorizationUrl(null);
}
#Override
protected void onPostExecute(String authURL) {
//send user to authorization page
android.webkit.CookieManager.getInstance().removeAllCookie();
mWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//check for our custom callback protocol otherwise use default behavior
if (url.startsWith(CALLBACK)) {
GetAccessToken getAccessToken = new GetAccessToken(url);
getAccessToken.execute();
return true;
}
if(mProgressDialog == null){
mProgressDialog = ProgressDialog.show(FacebookScribeLogin.this, null,
String.format(getString(R.string.talking_to_x), getString(R.string.facebook)), true, false);
}
return super.shouldOverrideUrlLoading(view, url);
}
#Override
public void onPageFinished(WebView view, String url) {
if(mProgressDialog != null){
mProgressDialog.hide();
mProgressDialog = null;
}
}
});
mWebView.loadUrl(authURL);
}
}
private class GetAccessToken extends AsyncTask<Void, Void, Void>{
private String mUrl, mToken, mSecret;
private GetAccessToken(String url) {
mUrl = url;
}
#Override
protected Void doInBackground(Void... voids) {
Uri uri = Uri.parse(mUrl);
String verifierStr = uri.getQueryParameter("code");
Verifier verifier = new Verifier(verifierStr);
//save this token for practical use.
Token accessToken = mAuthService.getAccessToken(null, verifier);
mToken = accessToken.getToken();
mSecret = accessToken.getSecret();
return null;
}
#Override
protected void onPostExecute(Void s) {
//mToken - save your mToken somehwere and perhaps use a graph API call for user details
}
}
}

Categories

Resources