package com.androidsocialnetworks.lib.impl;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
import com.androidsocialnetworks.lib.OAuthActivity;
import com.androidsocialnetworks.lib.OAuthSocialNetwork;
import com.androidsocialnetworks.lib.SocialNetworkAsyncTask;
import com.androidsocialnetworks.lib.SocialNetworkException;
import com.androidsocialnetworks.lib.SocialPerson;
import com.androidsocialnetworks.lib.listener.OnCheckIsFriendCompleteListener;
import com.androidsocialnetworks.lib.listener.OnLoginCompleteListener;
import com.androidsocialnetworks.lib.listener.OnPostingCompleteListener;
import com.androidsocialnetworks.lib.listener.OnRequestAddFriendCompleteListener;
import com.androidsocialnetworks.lib.listener.OnRequestRemoveFriendCompleteListener;
import com.androidsocialnetworks.lib.listener.OnRequestSocialPersonCompleteListener;
import java.io.File;
import java.util.UUID;
import twitter4j.Relationship;
import twitter4j.StatusUpdate;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.ConfigurationBuilder;
import static com.androidsocialnetworks.lib.Consts.TAG;
public class TwitterSocialNetwork extends OAuthSocialNetwork {
public static final int ID = 1;
private static final String SAVE_STATE_KEY_OAUTH_TOKEN = "TwitterSocialNetwork.SAVE_STATE_KEY_OAUTH_TOKEN";
private static final String SAVE_STATE_KEY_OAUTH_SECRET = "TwitterSocialNetwork.SAVE_STATE_KEY_OAUTH_SECRET";
private static final String SAVE_STATE_KEY_USER_ID = "TwitterSocialNetwork.SAVE_STATE_KEY_USER_ID";
private static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
// max 16 bit to use in startActivityForResult
private static final int REQUEST_AUTH = UUID.randomUUID().hashCode() & 0xFFFF;
private final String TWITTER_CALLBACK_URL = "oauth://AndroidSocialNetworks";
private final String fConsumerKey;
private final String fConsumerSecret;
private Twitter mTwitter;
private RequestToken mRequestToken;
public TwitterSocialNetwork(Fragment fragment, String consumerKey, String consumerSecret) {
super(fragment);
fConsumerKey = consumerKey;
fConsumerSecret = consumerSecret;
if (TextUtils.isEmpty(fConsumerKey) || TextUtils.isEmpty(fConsumerSecret)) {
throw new IllegalArgumentException("consumerKey and consumerSecret are invalid");
}
/*
*
* No authentication challenges found
* Relevant discussions can be found on the Internet at:
* http://www.google.co.jp/search?q=8e063946 or
* http://www.google.co.jp/search?q=ef59cf9f
*
* */
initTwitterClient();
}
private void initTwitterClient() {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(fConsumerKey);
builder.setOAuthConsumerSecret(fConsumerSecret);
String accessToken = mSharedPreferences.getString(SAVE_STATE_KEY_OAUTH_TOKEN, null);
String accessTokenSecret = mSharedPreferences.getString(SAVE_STATE_KEY_OAUTH_SECRET, null);
TwitterFactory factory = new TwitterFactory(builder.build());
if (TextUtils.isEmpty(accessToken) && TextUtils.isEmpty(accessTokenSecret)) {
mTwitter = factory.getInstance();
} else {
mTwitter = factory.getInstance(new AccessToken(accessToken, accessTokenSecret));
}
}
@Override
public int getID() {
return ID;
}
@Override
public boolean isConnected() {
String accessToken = mSharedPreferences.getString(SAVE_STATE_KEY_OAUTH_TOKEN, null);
String accessTokenSecret = mSharedPreferences.getString(SAVE_STATE_KEY_OAUTH_SECRET, null);
return accessToken != null && accessTokenSecret != null;
}
@Override
public com.androidsocialnetworks.lib.AccessToken getAccessToken() {
return new com.androidsocialnetworks.lib.AccessToken(
mSharedPreferences.getString(SAVE_STATE_KEY_OAUTH_TOKEN, null),
mSharedPreferences.getString(SAVE_STATE_KEY_OAUTH_SECRET, null)
);
}
@Override
public void requestLogin(OnLoginCompleteListener onLoginCompleteListener) {
super.requestLogin(onLoginCompleteListener);
executeRequest(new RequestLoginAsyncTask(), null, REQUEST_LOGIN);
}
@Override
public void logout() {
mSharedPreferences.edit()
.remove(SAVE_STATE_KEY_OAUTH_TOKEN)
.remove(SAVE_STATE_KEY_OAUTH_SECRET)
.remove(SAVE_STATE_KEY_USER_ID)
.apply();
mTwitter = null;
initTwitterClient();
}
@Override
public void requestCurrentPerson(OnRequestSocialPersonCompleteListener onRequestSocialPersonCompleteListener) {
super.requestCurrentPerson(onRequestSocialPersonCompleteListener);
executeRequest(new RequestGetPersonAsyncTask(), null, REQUEST_GET_CURRENT_PERSON);
}
@Override
public void requestSocialPerson(String userID, OnRequestSocialPersonCompleteListener onRequestSocialPersonCompleteListener) {
super.requestSocialPerson(userID, onRequestSocialPersonCompleteListener);
if (TextUtils.isEmpty(userID)) {
throw new SocialNetworkException("userID can't be null or empty");
}
Bundle args = new Bundle();
try {
args.putLong(RequestGetPersonAsyncTask.PARAM_USER_ID, Long.parseLong(userID));
} catch (NumberFormatException e) {
Log.e(TAG, "ERROR", e);
throw new SocialNetworkException("userID should be long number");
}
executeRequest(new RequestGetPersonAsyncTask(), args, REQUEST_GET_PERSON);
}
@Override
public void requestPostMessage(String message, OnPostingCompleteListener onPostingCompleteListener) {
super.requestPostMessage(message, onPostingCompleteListener);
Bundle args = new Bundle();
args.putString(RequestUpdateStatusAsyncTask.PARAM_MESSAGE, message);
executeRequest(new RequestUpdateStatusAsyncTask(), args, REQUEST_POST_MESSAGE);
}
@Override
public void requestPostPhoto(File photo, String message, OnPostingCompleteListener onPostingCompleteListener) {
super.requestPostPhoto(photo, message, onPostingCompleteListener);
Bundle args = new Bundle();
args.putString(RequestUpdateStatusAsyncTask.PARAM_MESSAGE, message);
args.putString(RequestUpdateStatusAsyncTask.PARAM_PHOTO_PATH, photo.getAbsolutePath());
executeRequest(new RequestUpdateStatusAsyncTask(), args, REQUEST_POST_PHOTO);
}
@Override
public void requestCheckIsFriend(String userID, OnCheckIsFriendCompleteListener onCheckIsFriendCompleteListener) {
super.requestCheckIsFriend(userID, onCheckIsFriendCompleteListener);
Bundle args = new Bundle();
try {
args.putLong(RequestCheckIsFriendAsyncTask.PARAM_USER_ID, Long.parseLong(userID));
} catch (NumberFormatException e) {
Log.e(TAG, "ERROR", e);
throw new SocialNetworkException("userID should be long number");
}
executeRequest(new RequestCheckIsFriendAsyncTask(), args, REQUEST_CHECK_IS_FRIEND);
}
@Override
public void requestAddFriend(String userID, OnRequestAddFriendCompleteListener onRequestAddFriendCompleteListener) {
super.requestAddFriend(userID, onRequestAddFriendCompleteListener);
Bundle args = new Bundle();
try {
args.putLong(RequestAddFriendAsyncTask.PARAM_USER_ID, Long.parseLong(userID));
} catch (NumberFormatException e) {
Log.e(TAG, "ERROR", e);
throw new SocialNetworkException("userID should be long number");
}
executeRequest(new RequestAddFriendAsyncTask(), args, REQUEST_ADD_FRIEND);
}
@Override
public void requestRemoveFriend(String userID, OnRequestRemoveFriendCompleteListener onRequestRemoveFriendCompleteListener) {
super.requestRemoveFriend(userID, onRequestRemoveFriendCompleteListener);
Bundle args = new Bundle();
try {
args.putLong(RequestRemoveFriendAsyncTask.PARAM_USER_ID, Long.parseLong(userID));
} catch (NumberFormatException e) {
Log.e(TAG, "ERROR", e);
throw new SocialNetworkException("userID should be long number");
}
executeRequest(new RequestRemoveFriendAsyncTask(), args, REQUEST_REMOVE_FRIEND);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_AUTH) return;
super.onActivityResult(requestCode, resultCode, data);
Uri uri = data != null ? data.getData() : null;
if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) {
String verifier = uri.getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);
RequestLogin2AsyncTask requestLogin2AsyncTask = new RequestLogin2AsyncTask();
mRequests.put(REQUEST_LOGIN2, requestLogin2AsyncTask);
Bundle args = new Bundle();
args.putString(RequestLogin2AsyncTask.PARAM_VERIFIER, verifier);
requestLogin2AsyncTask.execute(args);
} else {
if (mLocalListeners.get(REQUEST_LOGIN) != null) {
mLocalListeners.get(REQUEST_LOGIN).onError(getID(), REQUEST_LOGIN, "incorrect URI returned: " + uri, null);
mLocalListeners.remove(REQUEST_LOGIN);
}
/*
*
* No authentication challenges found
* Relevant discussions can be found on the Internet at:
* http://www.google.co.jp/search?q=8e063946 or
* http://www.google.co.jp/search?q=ef59cf9f
*
* */
initTwitterClient();
}
}
@Override
public void cancelLoginRequest() {
super.cancelLoginRequest();
initTwitterClient();
}
private class RequestLoginAsyncTask extends SocialNetworkAsyncTask {
private static final String RESULT_OAUTH_LOGIN = "LoginAsyncTask.RESULT_OAUTH_LOGIN";
@Override
protected Bundle doInBackground(Bundle... params) {
Bundle result = new Bundle();
try {
mRequestToken = mTwitter.getOAuthRequestToken(TWITTER_CALLBACK_URL);
Uri oauthLoginURL = Uri.parse(mRequestToken.getAuthenticationURL() + "&force_login=true");
result.putString(RESULT_OAUTH_LOGIN, oauthLoginURL.toString());
} catch (TwitterException e) {
Log.e(TAG, "ERROR", e);
result.putString(RESULT_ERROR, e.getMessage() == null ? "canceled" : e.getMessage());
}
return result;
}
@Override
protected void onPostExecute(Bundle result) {
if (!handleRequestResult(result, REQUEST_LOGIN)) return;
if (result.containsKey(RESULT_OAUTH_LOGIN)) {
Intent intent = new Intent(mSocialNetworkManager.getActivity(), OAuthActivity.class)
.putExtra(OAuthActivity.PARAM_CALLBACK, TWITTER_CALLBACK_URL)
.putExtra(OAuthActivity.PARAM_URL_TO_LOAD, result.getString(RESULT_OAUTH_LOGIN));
mSocialNetworkManager.startActivityForResult(intent, REQUEST_AUTH);
}
}
}
private class RequestLogin2AsyncTask extends SocialNetworkAsyncTask {
public static final String PARAM_VERIFIER = "Login2AsyncTask.PARAM_VERIFIER";
private static final String RESULT_TOKEN = "Login2AsyncTask.RESULT_TOKEN";
private static final String RESULT_SECRET = "Login2AsyncTask.RESULT_SECRET";
private static final String RESULT_USER_ID = "Login2AsyncTask.RESULT_USER_ID";
@Override
protected Bundle doInBackground(Bundle... params) {
String verifier = params[0].getString(PARAM_VERIFIER);
Bundle result = new Bundle();
try {
AccessToken accessToken = mTwitter.getOAuthAccessToken(mRequestToken, verifier);
result.putString(RESULT_TOKEN, accessToken.getToken());
result.putString(RESULT_SECRET, accessToken.getTokenSecret());
result.putLong(RESULT_USER_ID, accessToken.getUserId());
} catch (Exception e) {
Log.e(TAG, "ERROR", e);
result.putString(RESULT_ERROR, e.getMessage() == null ? "canceled" : e.getMessage());
}
return result;
}
@Override
protected void onPostExecute(Bundle result) {
mRequests.remove(REQUEST_LOGIN2);
if (!handleRequestResult(result, REQUEST_LOGIN)) {
initTwitterClient();
return;
}
// Shared Preferences
mSharedPreferences.edit()
.putString(SAVE_STATE_KEY_OAUTH_TOKEN, result.getString(RESULT_TOKEN))
.putString(SAVE_STATE_KEY_OAUTH_SECRET, result.getString(RESULT_SECRET))
.putLong(SAVE_STATE_KEY_USER_ID, result.getLong(RESULT_USER_ID))
.apply();
initTwitterClient();
if (mLocalListeners.get(REQUEST_LOGIN) != null) {
((OnLoginCompleteListener) mLocalListeners.get(REQUEST_LOGIN)).onLoginSuccess(getID());
}
mLocalListeners.remove(REQUEST_LOGIN);
}
}
private class RequestGetPersonAsyncTask extends SocialNetworkAsyncTask {
public static final String PARAM_USER_ID = "RequestGetPersonAsyncTask.PARAM_USER_ID";
private static final String RESULT_IS_CURRENT_PERSON = "RequestPersonAsyncTask.RESULT_IS_CURRENT_PERSON";
private static final String RESULT_ID = "RequestPersonAsyncTask.RESULT_ID";
private static final String RESULT_NAME = "RequestPersonAsyncTask.RESULT_NAME";
private static final String RESULT_AVATAR_URL = "RequestPersonAsyncTask.RESULT_AVATAR_URL";
private static final String RESULT_PROFILE_URL = "RequestPersonAsyncTask.RESULT_PROFILE_URL";
private static final String RESULT_NICKNAME = "RequestPersonAsyncTask.RESULT_NICKNAME";
@Override
protected Bundle doInBackground(Bundle... params) {
Bundle args = params[0];
Bundle result = new Bundle();
Long userID;
if (args.containsKey(PARAM_USER_ID)) {
userID = args.getLong(PARAM_USER_ID);
result.putBoolean(RESULT_IS_CURRENT_PERSON, false);
} else {
userID = mSharedPreferences.getLong(SAVE_STATE_KEY_USER_ID, -1);
result.putBoolean(RESULT_IS_CURRENT_PERSON, true);
}
try {
User user = mTwitter.showUser(userID);
result.putString(RESULT_ID, user.getId() + "");
result.putString(RESULT_NAME, user.getName());
result.putString(RESULT_AVATAR_URL, user.getBiggerProfileImageURL());
result.putString(RESULT_PROFILE_URL, "https://twitter.com/" + user.getScreenName());
result.putString(RESULT_NICKNAME, user.getScreenName());
} catch (TwitterException e) {
Log.e(TAG, "ERROR", e);
result.putString(RESULT_ERROR, e.getMessage());
}
return result;
}
@Override
protected void onPostExecute(Bundle result) {
if (result.getBoolean(RESULT_IS_CURRENT_PERSON)) {
if (!handleRequestResult(result, REQUEST_GET_CURRENT_PERSON)) return;
SocialPerson socialPerson = initSocialPerson(result);
((OnRequestSocialPersonCompleteListener) mLocalListeners.get(REQUEST_GET_CURRENT_PERSON))
.onRequestSocialPersonSuccess(getID(), socialPerson);
mLocalListeners.remove(REQUEST_GET_CURRENT_PERSON);
} else {
if (!handleRequestResult(result, REQUEST_GET_PERSON)) return;
SocialPerson socialPerson = initSocialPerson(result);
((OnRequestSocialPersonCompleteListener) mLocalListeners.get(REQUEST_GET_PERSON))
.onRequestSocialPersonSuccess(getID(), socialPerson);
mLocalListeners.remove(REQUEST_GET_PERSON);
}
}
private SocialPerson initSocialPerson(Bundle result) {
SocialPerson socialPerson = new SocialPerson();
socialPerson.id = result.getString(RESULT_ID);
socialPerson.name = result.getString(RESULT_NAME);
socialPerson.avatarURL = result.getString(RESULT_AVATAR_URL);
socialPerson.profileURL = result.getString(RESULT_PROFILE_URL);
socialPerson.nickname = result.getString(RESULT_NICKNAME);
return socialPerson;
}
}
private class RequestUpdateStatusAsyncTask extends SocialNetworkAsyncTask {
public static final String PARAM_MESSAGE = "RequestUpdateStatusAsyncTask.PARAM_MESSAGE";
public static final String PARAM_PHOTO_PATH = "RequestUpdateStatusAsyncTask.PARAM_PHOTO_PATH";
private static final String RESULT_POST_PHOTO = "RequestUpdateStatusAsyncTask.RESULT_POST_PHOTO";
@Override
protected Bundle doInBackground(Bundle... params) {
Bundle args = params[0];
Bundle result = new Bundle();
String paramMessage = "";
String paramPhotoPath = null;
if (args.containsKey(PARAM_MESSAGE)) {
paramMessage = args.getString(PARAM_MESSAGE);
}
if (args.containsKey(PARAM_PHOTO_PATH)) {
paramPhotoPath = args.getString(PARAM_PHOTO_PATH);
result.putBoolean(RESULT_POST_PHOTO, true);
} else {
result.putBoolean(RESULT_POST_PHOTO, false);
}
try {
StatusUpdate status = new StatusUpdate(paramMessage);
if (paramPhotoPath != null) {
status.setMedia(new File(paramPhotoPath));
}
Log.d(TAG, "RequestUpdateStatusAsyncTask.mTwitter.updateStatus");
mTwitter.updateStatus(status);
} catch (TwitterException e) {
Log.e(TAG, "ERROR", e);
result.putString(RESULT_ERROR, e.getMessage());
}
return result;
}
@Override
protected void onPostExecute(Bundle result) {
String requestID = result.getBoolean(RESULT_POST_PHOTO) ? REQUEST_POST_PHOTO : REQUEST_POST_MESSAGE;
mRequests.remove(requestID);
String error = result.containsKey(RESULT_ERROR) ? result.getString(RESULT_ERROR) : null;
if (mLocalListeners.get(requestID) != null) {
if (error == null) {
((OnPostingCompleteListener) mLocalListeners.get(requestID)).onPostSuccessfully(getID());
} else {
mLocalListeners.get(requestID).onError(getID(), requestID, error, null);
}
}
mLocalListeners.remove(requestID);
}
@Override
protected void onCancelled() {
Log.d(TAG, "RequestUpdateStatusAsyncTask.onCancelled");
}
}
private class RequestCheckIsFriendAsyncTask extends SocialNetworkAsyncTask {
public static final String PARAM_USER_ID = "PARAM_USER_ID";
public static final String RESULT_IS_FRIEND = "RESULT_IS_FRIEND";
public static final String RESULT_REQUESTED_ID = "RESULT_REQUESTED_ID";
@Override
protected Bundle doInBackground(Bundle... params) {
Bundle args = params[0];
Bundle result = new Bundle();
Long userID = args.getLong(PARAM_USER_ID);
result.putLong(RESULT_REQUESTED_ID, userID);
try {
long currentUserID = mSharedPreferences.getLong(SAVE_STATE_KEY_USER_ID, -1);
Relationship relationship = mTwitter.showFriendship(currentUserID, userID);
result.putBoolean(RESULT_IS_FRIEND, relationship.isSourceFollowingTarget());
} catch (TwitterException e) {
Log.e(TAG, "ERROR", e);
result.putString(RESULT_ERROR, e.getMessage());
}
return result;
}
@Override
protected void onPostExecute(Bundle result) {
if (!handleRequestResult(result, REQUEST_CHECK_IS_FRIEND,
result.getLong(RESULT_REQUESTED_ID))) return;
((OnCheckIsFriendCompleteListener) mLocalListeners.get(REQUEST_CHECK_IS_FRIEND))
.onCheckIsFriendComplete(getID(),
"" + result.getLong(RESULT_REQUESTED_ID),
result.getBoolean(RESULT_IS_FRIEND)
);
}
}
private class RequestAddFriendAsyncTask extends SocialNetworkAsyncTask {
public static final String PARAM_USER_ID = "PARAM_USER_ID";
public static final String RESULT_REQUESTED_ID = "RESULT_REQUESTED_ID";
@Override
protected Bundle doInBackground(Bundle... params) {
Bundle args = params[0];
Bundle result = new Bundle();
Long userID = args.getLong(PARAM_USER_ID);
result.putLong(RESULT_REQUESTED_ID, userID);
try {
mTwitter.createFriendship(userID);
} catch (TwitterException e) {
Log.e(TAG, "ERROR", e);
result.putString(RESULT_ERROR, e.getMessage());
}
return result;
}
@Override
protected void onPostExecute(Bundle result) {
if (!handleRequestResult(result, REQUEST_ADD_FRIEND,
result.getLong(RESULT_REQUESTED_ID))) return;
((OnRequestAddFriendCompleteListener) mLocalListeners.get(REQUEST_ADD_FRIEND))
.onRequestAddFriendComplete(getID(),
"" + result.getLong(RESULT_REQUESTED_ID)
);
}
}
private class RequestRemoveFriendAsyncTask extends SocialNetworkAsyncTask {
public static final String PARAM_USER_ID = "PARAM_USER_ID";
public static final String RESULT_REQUESTED_ID = "RESULT_REQUESTED_ID";
@Override
protected Bundle doInBackground(Bundle... params) {
Bundle args = params[0];
Bundle result = new Bundle();
Long userID = args.getLong(PARAM_USER_ID);
result.putLong(RESULT_REQUESTED_ID, userID);
try {
mTwitter.destroyFriendship(userID);
} catch (TwitterException e) {
Log.e(TAG, "ERROR", e);
result.putString(RESULT_ERROR, e.getMessage());
}
return result;
}
@Override
protected void onPostExecute(Bundle result) {
if (!handleRequestResult(result, REQUEST_REMOVE_FRIEND,
result.getLong(RESULT_REQUESTED_ID))) return;
((OnRequestRemoveFriendCompleteListener) mLocalListeners.get(REQUEST_REMOVE_FRIEND))
.onRequestRemoveFriendComplete(getID(),
"" + result.getLong(RESULT_REQUESTED_ID)
);
}
}
}