Integrate twitter in my app, when user logged in through twitter I show the follower list for sending messages but when called /1.1/followers/list.json API I got the null response , Do I need any permission to access API ?
{protocol=h2, code=400, message=, url=https://api.twitter.com/1.1/followers/list.json?screen_name=(screenname)&cursor=-1&skip_status=true}
loginButton.setCallback(new Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> result) {
e("********", "----result--->>>>" + result.response);
/* TwitterSession session = TwitterCore.getInstance().getSessionManager().getActiveSession();
TwitterAuthToken authToken = session.getAuthToken();
String token = authToken.token;
String secret = authToken.secret; */
/***********************After login****************/
APIService inf1 = MyApplication.getRetro(Login.this, "https://api.twitter.com").create(APIService.class);
final Call<JsonElement> res1 = inf1.show("-1","(screenName)",true,false);
// "/1.1/followers/list.json?include_user_entities=false&screen_name=twitterdev&skip_status=true&cursor=-1
res1.enqueue(new retrofit2.Callback<JsonElement>() {
#Override
public void onResponse(#NonNull Call<JsonElement> call, #NonNull Response<JsonElement> response) {
try {
JSONObject mReturn = new JSONObject(response.body().toString());
e("-------->>", "*******onResponse*******"+mReturn);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(#NonNull Call<JsonElement> call, #NonNull Throwable t) {
}
});
/************************************************/
}
#Override
public void failure(TwitterException exception) {
// Do something on failure
}
});
API:
#GET("/1.1/followers/list.json")
Call<JsonElement> show( #Query("cursor")String cursor,
#Query("screen_name")String var,
#Query("skip_status")boolean skip_status,
#Query("include_user_entities")boolean include_user_entities);
Related
i have setup retrofit client and the api interface, i have some code as follows
public Result<LoggedInUser> login(String username, String password) {
try {
apiInterface = ApiClient.getClient().create(ApiInterface.class);
RequestData requestData = new RequestData(username, password);
Call<RequestResponse> call = apiInterface.login(requestData);
call.enqueue(new Callback<RequestResponse>() {
#Override
public void onResponse(Call<RequestResponse> call, Response<RequestResponse> response) {
RequestResponse resource = response.body();
System.out.println(resource.getData().getAccessToken());
}
#Override
public void onFailure(Call<RequestResponse> call, Throwable t) {
call.cancel();
}
});
LoggedInUser fakeUser = new LoggedInUser(
java.util.UUID.randomUUID().toString(),
"Jane Doe");
return new Result.Success<>(fakeUser);
} catch (Exception e) {
return new Result.Error(new IOException("Error logging in", e));
}
}
I am not familar with the pattern that should be used to notify the repository class when the rest call obtains it's response.
the above code is called from the following code in the repository class
public Result<LoggedInUser> login(String username, String password) {
// handle login
Result<LoggedInUser> result = dataSource.login(username, password);
if (result instanceof Result.Success) {
setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
}
return result;
}
I am working with an Android Recyclerview with Retrofit, it is working without any Post Data. I need to post some data in my current Code.
Below is my Current ApiInterface
public interface ApiInterface {
#GET("mypage.php")
Call<Pojo> getData();
}
And in my activity I am calling this by below code
ApiInterface apiInterface = (ApiInterface) RetrofitClient.getRetrofitInstance().create(ApiInterface.class);
Call<Pojo> listingdata = apiInterface.getData();
listingdata.enqueue(new Callback<Pojo>() {
#Override
public void onResponse(Call<Pojo> call, Response<Pojo> response) {
if(response.isSuccessful()){
recycleradpter recycleradpter = new recycleradpter(response.body().getData());
recyclerView.setAdapter(recycleradpter);
progressbar2.setVisibility(View.GONE);
}
}
#Override
public void onFailure(Call<Pojo> call, Throwable t) {
//System.out.println("12345678934567890234567890");
//Toast.makeText(getActivity(), "No Connected internet", Toast.LENGTH_SHORT).show();
progressbar2.setVisibility(View.GONE);
dialogfunction();
}
});
How Can I get data based on passed data in above code
If you want to send a post request then you have to create a method like below. The calling of the method will be similar to that of get request. Just pass the parameters of your post body. You can for details here.
#POST("mypage.php")
Call<Pojo> postData(
#Field("param1") String param1,
#Field("param2") int param2
);
#FormUrlEncoded
#POST("your_php_file.php")
Call<ResponseBody> getLanguageCall(#Field("lang_code") String lang_code, #Field("app_id") String app_id);
private void getLanguageCall() {
progressDialog.setVisibility(VISIBLE);
Call<ResponseBody> call = ApiClient.getClient().create(ApiInterface.class).getLanguageCall(PreferenceManager.getStringPreference(SplashActivity.this, appLanguage), PreferenceManager.getStringPreference(SplashActivity.this, PreferenceManager.APP_ID));
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
progressDialog.setVisibility(View.GONE);
if (!response.isSuccessful()) {
showToast(response.code() + " : " + response.message());
return;
}
try {
JSONObject root = new JSONObject(response.body().string());
HashMap<String, String> list = new HashMap<String, String>();
JSONArray keyData = root.getJSONArray("key_data");
for (int i = 0; i < keyData.length(); i++) {
JSONObject obj = keyData.getJSONObject(i);
list.put(obj.getString("Key_Name").toLowerCase(), obj.getString("Key_Value"));
}
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
progressDialog.setVisibility(View.GONE);
showToast("Error ! Server Error.");
}
});
}
I'm creating an authorization app, where user registers and gets client_id, client_secret, access_token and refresh_token. I have one API where i need to do call. In that call I use my access_token. All works great. But the access_token expires after hour, so with refresh_token I'm updating my access_token, but the new access_token not works. When I'm doing call with this new access_token, the response body message is "expired access_token provided". In postman all works good. When I'm getting new access_token, in server visible only the access_token that i got from registration. So in server the access_token not updating. But when I'm doing this in postman, the access_token in server changes. So what's the problem, that in postman he updates the access_token, and in server the access_token changes, but when I'm updating in phone, the access_token in server not changes. I done debugging and i see that I'm getting new access_token. So where's the problem?
public interface SupportopApi {
//Post request for user register
#POST("/api/registration")
Call<ResponseBody> registrationRequest(#Body SupportopObjRegistration supportopObjRegistration);
//Post request for user activation
#POST("/api/getClientCD")
Call<ResponseBody> clientActivationRequest(#Body SupportopObjClient activate);
//Get request for getting token
#GET("/api/getToken")
Call<ResponseBody> getTokenRequest(#Query("grant_type") String grant_type,
#Query("client_id") String client_id,
#Query("client_secret") String client_secret,
#Query("email") String email,
#Query("password") String password);
//The call where i use my access_token
#GET("/api/getLanguages")
Call<ResponseBody> getLanguages(#Header("Content-Type") String json,
#Header("Authorization") String token,
#Header("Cache-Control") String cache);}
Here's the retrofit and OkHttpClient initialize part.
public class ApiClient {
private static ApiClient instance;
private SupportopApi supportopApi;
client.addInterceptor(new Interceptor() {
#Override
public Response intercept(#NonNull Chain chain) throws IOException {
Request request = chain.request();
request = request.newBuilder()
.build();
return chain.proceed(request);
}
});
supportopApi = new Retrofit.Builder()
.baseUrl(endpoint)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(SupportopApi.class);
}
public static synchronized void initializeInstance(String endpoint) {
if (instance == null) {
instance = new ApiClient(endpoint);
}
}
public static synchronized ApiClient getInstance() {
if (instance == null) {
throw new IllegalStateException("PentairAPIClient has not been initialized.");
}
return instance;
}
public Call<ResponseBody> registration(SupportopObjRegistration supportopObjRegistration) {
return supportopApi.registrationRequest(supportopObjRegistration);
}
public Call<ResponseBody> activation(SupportopObjClient activate) {
return supportopApi.clientActivationRequest(activate);
}
public Call<ResponseBody> getToken(String grant_type, String client_id, String client_secret,
String email, String password) {
return supportopApi.getTokenRequest(grant_type, client_id, client_secret, email, password);
}
public Call<ResponseBody> getLanguage(String token) {
String new_token = "Bearer " + token;
return supportopApi.getLanguages("application/json", new_token, "no-cache");
}
}
Registration works great, so I'll show you only the login call.
public class LoginFragment extends BaseFragment {
private View mainView;
private ApiClient apiClient;
private EditText email, password;
private Button userLogin;
private SupportopObjClient supportopClientActivate;
#Override
public String toString() {
return "LoginFragment";
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mainView = inflater.inflate(R.layout.login_fragment, container, false);
init(mainView);
return mainView;
}
private void init(final View v) {
apiClient = ApiClient.getInstance();
email = (EditText) v.findViewById(R.id.login_email);
password = (EditText) v.findViewById(R.id.login_password);
userLogin = (Button) v.findViewById(R.id.user_login);
userLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
supportopClientActivate.setUsername("");
supportopClientActivate.setEmail(email.getText().toString());
supportopClientActivate.setPassword(password.getText().toString());
supportopClientActivate.setType("generic");
getClient();
}
});
}
public void getClient() {
Call<ResponseBody> callActive = apiClient.activation(supportopClientActivate);
callActive.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
//Parsing the data from Json to string
String data = response.body().string();
JSONObject obj = new JSONObject(data);
String client_id = obj.getString("client_id");
String client_secret = obj.getString("client_secret");
//Saving clientID and clientSecret in phone storage
SharedPreferencesManager.getInstance().setClientID(client_id);
SharedPreferencesManager.getInstance().setClientSecret(client_secret);
//Calling the tokenCall method to get access token and refresh token
loginCall(client_id, client_secret);
} catch (JSONException | IOException e) {
e.printStackTrace();
}
} else {
//if the response not successful
Toast.makeText(getActivity(), "user doesn't exist", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(getActivity(), "An error occurred", Toast.LENGTH_SHORT).show();
}
});
}
public void loginCall(String client_id, final String client_secret) {
Call<ResponseBody> token = apiClient.getToken("password", client_id, client_secret,
supportopClientActivate.getEmail(), supportopClientActivate.getPassword());
token.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
//Parsing the data from Json to string
String dataAccess = response.body().string();
JSONObject obj = new JSONObject(dataAccess);
String access_token = obj.getString("accessToken");
String refresh_token = obj.getString("refreshToken");
Toast.makeText(context, access_token, Toast.LENGTH_SHORT).show();
SharedPreferencesManager.getInstance().setAccessToken(access_token);
SharedPreferencesManager.getInstance().setRefreshToken(refresh_token);
Toast.makeText(context, SharedPreferencesManager.getInstance().getAccessToken(), Toast.LENGTH_SHORT).show();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getActivity(), "password or email are incorrect or doesn't exist",
Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(getActivity(), "An error occurred", Toast.LENGTH_SHORT).show();
}
});
}
I am using Fabric sdk for Twitter. In this I am able to make login request as it's described in its document. Now I wan't to get list of follower of logged in user and show in RecycleView with follower name and profile image. I have tried various solutions like:
private void getFollowersdReq(long userID) {
showProgressDialog();
JsonObjectRequest getRegisterReq = new JsonObjectRequest(Request.Method.GET,
"https://api.twitter.com/1.1/followers/list.json?cursor=-1&&skip_status=true&include_user_entities=false&user_id=" + userID, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
LogUtils.LOGD("Server Response", response.toString());
hideProgressDialog();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("server Error",
"Error: " + error.getMessage());
Toast.makeText(getActivity(),
"Error:" + error.getMessage(), Toast.LENGTH_LONG).show();
hideProgressDialog();
}
}) {
/**
* Passing some request headers
* */
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("Accept", "application/json");
return headers;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(getRegisterReq, new SignpostUrlStack(twitterToken, secret));
// Cancelling request
// ApplicationController.getInstance().getRequestQueue().cancelAll(tag_json_obj);
}
In above code I am calling Twitter API to get list of followers but in this I am getting error message
{
"errors": [
{
"code": 215,
"message": "Bad Authentication data."
}
]
}
Also I have tried
class MyTwitterApiClient extends TwitterApiClient {
public MyTwitterApiClient(TwitterSession session) {
super(session);
}
public CustomService getCustomService() {
return getService(CustomService.class);
}
public UsersService getUsersService() {
return getService(UsersService.class);
}
}
interface CustomService {
#GET("/1.1/followers/list.json")
void show(#Query("user_id") Long userId,
#Query("screen_name") String var,
#Query("skip_status") Boolean var1,
#Query("include_user_entities") Boolean var2,
#Query("count") Integer var3, Callback<User> cb);
}
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);
}
Called this class like:
new MyTwitterApiClient(session).getCustomService().show(userID, null, true, true, 100, new Callback<User>() {
#Override
public void success(Result<User> result) {
LogUtils.LOGI("Get success",result.toString());
}
#Override
public void failure(TwitterException e) {
hideProgressDialog();
}
});
By this method also I am not able to get desired output.
The second method (using TwitterApiClient) is almost correct except for the response data model. Refere https://dev.twitter.com/rest/reference/get/followers/list for the structure of the response. You need to build a data model according to this structure.
Here is the fix :
//data model
public class Followers {
#SerializedName("users")
public final List<User> users;
public Followers(List<User> users) {
this.users = users;
}
}
class MyTwitterApiClient extends TwitterApiClient {
public MyTwitterApiClient(TwitterSession session) {
super(session);
}
public CustomService getCustomService() {
return getService(CustomService.class);
}
}
interface CustomService {#GET("/1.1/followers/list.json")
void show(#Query("user_id") Long userId, #Query("screen_name") String
var, #Query("skip_status") Boolean var1, #Query("include_user_entities") Boolean var2, #Query("count") Integer var3, Callback < Followers > cb);
}
new MyTwitterApiClient(session).getCustomService().show(userID, null, true, true, 100, new Callback < Followers > () {#Override
public void success(Result < Followers > result) {
Log.i("Get success", "" + result.data.users.size());
}
#Override
public void failure(TwitterException e) {
}
});
The above code is working for me. Hope it helps!
MyTwitterApiClient.java
import com.twitter.sdk.android.core.Callback;
import com.twitter.sdk.android.core.TwitterApiClient;
import com.twitter.sdk.android.core.TwitterSession;
import retrofit.client.Response;
import retrofit.http.GET;
import retrofit.http.Query;
public class MyTwitterApiClient extends TwitterApiClient {
public MyTwitterApiClient(TwitterSession session) {
super(session);
}
/**
* Provide CustomService with defined endpoints
*/
public CustomService getCustomService() {
return getService(CustomService.class);
}
}
// example users/show service endpoint
interface CustomService {
#GET("/1.1/followers/ids.json")
void list(#Query("user_id") long id, Callback<Response> cb);
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
// Note: Your consumer key and secret should be obfuscated in your source code before shipping.
private static final String TWITTER_KEY = "YOUR_TWITTER_KEY";
private static final String TWITTER_SECRET = "YOUR_TWITTER_SECRET";
TwitterLoginButton loginButton;
SharedPreferences shared;
#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());
setContentView(R.layout.activity_main);
shared = getSharedPreferences("demotwitter", Context.MODE_PRIVATE);
loginButton = (TwitterLoginButton) findViewById(R.id.login_button);
loginButton.setCallback(new Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> result) {
// Do something with result, which provides a TwitterSession for making API calls
TwitterSession session = Twitter.getSessionManager()
.getActiveSession();
TwitterAuthToken authToken = session.getAuthToken();
String token = authToken.token;
String secret = authToken.secret;
//Here we get all the details of user's twitter account
System.out.println(result.data.getUserName()
+ result.data.getUserId());
Twitter.getApiClient(session).getAccountService()
.verifyCredentials(true, false, new Callback<User>() {
#Override
public void success(Result<User> userResult) {
User user = userResult.data;
//Here we get image url which can be used to set as image wherever required.
System.out.println(user.profileImageUrl+" "+user.email+""+user.followersCount);
}
#Override
public void failure(TwitterException e) {
}
});
shared.edit().putString("tweetToken", token).commit();
shared.edit().putString("tweetSecret", secret).commit();
TwitterAuthClient authClient = new TwitterAuthClient();
authClient.requestEmail(session, new Callback<String>() {
#Override
public void success(Result<String> result) {
// Do something with the result, which provides the
// email address
System.out.println(result.toString());
Log.d("Result", result.toString());
Toast.makeText(getApplicationContext(), result.data,
Toast.LENGTH_LONG).show();
}
#Override
public void failure(TwitterException exception) {
// Do something on failure
System.out.println(exception.getMessage());
}
});
MyTwitterApiClient apiclients=new MyTwitterApiClient(session);
apiclients.getCustomService().list(result.data.getUserId(), new Callback<Response>() {
#Override
public void failure(TwitterException arg0) {
// TODO Auto-generated method stub
}
#Override
public void success(Result<Response> arg0) {
// TODO Auto-generated method stub
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(arg0.response.getBody().in()));
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
String result = sb.toString();
System.out.println("Response is>>>>>>>>>"+result);
try {
JSONObject obj=new JSONObject(result);
JSONArray ids=obj.getJSONArray("ids");
//This is where we get ids of followers
for(int i=0;i<ids.length();i++){
System.out.println("Id of user "+(i+1)+" is "+ids.get(i));
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
#Override
public void failure(TwitterException exception) {
// Do something on failure
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Pass the activity result to the login button.
loginButton.onActivityResult(requestCode, resultCode, data);
}
}
I'm logging in with twitter using Fabric.
This is how I fetch the user data:
loginButton.setCallback(new Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> result) {
// Do something with result, which provides a TwitterSession for making API calls
AccountService ac = Twitter.getApiClient(result.data).getAccountService();
ac.verifyCredentials(true, true, new Callback<com.twitter.sdk.android.core.models.User>() {
#Override
public void success(Result<com.twitter.sdk.android.core.models.User> result) {
String imageUrl = result.data.profileImageUrl;
String email = result.data.email;
String userName = result.data.name;
System.out.println(imageUrl);
System.out.println(email);
System.out.println(userName);
}
#Override
public void failure(TwitterException e) {
}
});
}
This is working fine, except that the email variable is null when I print to log. Is there an other way of fetching the user email?
-Here is the Solution!
twitauthobj.requestEmail(twitsessionobj,new Callback<String>() {
#Override
public void success(Result<String> stringResult) {
'You code here'
}
#Override
public void failure(TwitterException e) {
}
});
-Thanks let me inform if t doesnt work!
To bypass Twitter's useless request email activity and to fix a leak, I dug through the source code and pulled this out:
new Retrofit.Builder()
.client(getClient(sessionResult))
.baseUrl(new TwitterApi().getBaseHostUrl())
.addConverterFactory(getFactory())
.build()
.create(EmailService.class)
.getEmail()
.enqueue(new Callback<User>() {
#Override
public void success(Result<User> result) {
String email = result.data.email;
// Handle the result
if (email == null) {
TwitterProvider.this.failure(
new TwitterException("Your application may not have access to"
+ " email addresses or the user may not have an email address. To request"
+ " access, please visit https://support.twitter.com/forms/platform."));
} else if (email.equals("")) {
TwitterProvider.this.failure(
new TwitterException("This user does not have an email address."));
} else {
mCallbackObject.onSuccess(createIdpResponse(sessionResult.data, email));
}
}
#Override
public void failure(TwitterException exception) {
TwitterProvider.this.failure(exception);
}
});
private OkHttpClient getClient(Result<TwitterSession> sessionResult) {
return OkHttpClientHelper.getOkHttpClient(
sessionResult.data,
TwitterCore.getInstance().getAuthConfig(),
TwitterCore.getInstance().getSSLSocketFactory());
}
private GsonConverterFactory getFactory() {
return GsonConverterFactory.create(
new GsonBuilder()
.registerTypeAdapterFactory(new SafeListAdapter())
.registerTypeAdapterFactory(new SafeMapAdapter())
.registerTypeAdapter(BindingValues.class, new BindingValuesAdapter())
.create());
}
EmailService:
interface EmailService {
#GET("/1.1/account/verify_credentials.json?include_email=true?include_entities=true?skip_status=true")
Call<User> getEmail();
}