I am now using retrofit,OkHttp and facebook sdk to make facebook registration.But I have problems in my register method "Fail:: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $".Could you look at that please?Here is my code.This is facebook resigter event.
loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(
JSONObject object,
GraphResponse response) {
try {
user_id = response.getJSONObject().get("id") + "";
Log.i("User id", user_id);
register(user_id);
setProfile();
} catch (JSONException e) {
e.printStackTrace();
}
try {
response.getJSONObject().get("id");
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender, birthday");
request.setParameters(parameters);
request.executeAsync();
}
#Override
public void onCancel() {
}
#Override
public void onError(FacebookException error) {
}
});
This is my register method.
public void register(String id){
String pic_link="https://graph.facebook.com/" + id + "/picture?type=large";
Call<HashMap<String,String>> register= Login_api.createService(Login_service.class).register(id,pic_link);
register.enqueue(new Callback<HashMap<String, String>>() {
#Override
public void onResponse(Response<HashMap<String, String>> response, Retrofit retrofit) {
Log.i("SUCCESS:","MOTHER FUCKER");
}
#Override
public void onFailure(Throwable t) {
Log.i("Fail:",t.getMessage());
}
});
}
This is my api class
public class Login_api {
private static Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://192.168.0.111")
.addConverterFactory(GsonConverterFactory.create())
.client(new MyOkHttp());
public Login_api(){
}
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.build();
return retrofit.create(serviceClass);
}
}
And this is my Service interface
public interface Login_service {
#FormUrlEncoded
#POST("androidapi/public/post/store")
Call<HashMap<String,String>> register(
#Field("user_name") String user_name,
#Field("profile_pic") String profile_pic
);
}
Hard to say for sure without more stack trace, but I'd say that you are not responding with valid JSON on your backend (http://192.168.0.111), since the error message you're getting is when Gson finds something other than a { as the first char in the response.
Related
I am using android as my front-end application and Spring boot as server part. I am using android retrofit library to connect with server.
When user logs onto server, he gets response like this.
So how do I extract "accessToken" and "tokenType" from body response?
Here is my login method in android:
private void login(LoginRequest loginRequest) {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClientBuilder.addInterceptor(logging);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClientBuilder.build());
Retrofit retrofit = builder.build();
RestAPI client = retrofit.create(RestAPI.class);
Call<LoginRequest> call = client.signIn(loginRequest);
call.enqueue(new Callback<LoginRequest>() {
#Override
public void onResponse(Call<LoginRequest> call, Response<LoginRequest> response) {
if (response.code() == 200) {
Toast.makeText(getApplicationContext(), response.body().toString(),
Toast.LENGTH_LONG).show();
Intent i = new Intent(LoginActivity.this, PostsActivity.class);
//response.body should be somewhere here
startActivity(i);
}else{
Toast.makeText(getApplicationContext(), "Uneti podaci nisu dobri",
Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<LoginRequest> call, Throwable t) {
}
});
}
This is my LoginRequest class
public class LoginRequest {
private String username;
private String password;
public LoginRequest(String username, String password) {
this.username = username;
this.password = password;
}
}
Create model class for response like below
public class Token {
#SerializedName("tokenType")
private String tokenType;
#SerializedName("accessToken")
private String accessToken;
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}
Then change the Api return type to Call<Token>
Accordingly you also need to modify the call
call.enqueue(new Callback<Token>() {
#Override
public void onResponse(Call<Token> call, Response<Token> response) {
if(response.isSuccessful()) {
Token token = response.body();
}
}
#Override
public void onFailure(Call<Token> call, Throwable t) {
}
});
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 want to post user credentials to following url
: http://myurl/authenticate
Parameters : login. Type (JSON)
username : string
password : string
"login":{"username": "JohnDoe","password": "eoDnhoJ" }
If success
{
" r e s u l t " : " S u c c e s s " ,
"response": "Users Session ID"
}
Here is my code
public interface APIService {
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
}
public class ApiUtils {
private ApiUtils() {}
public static final String BASE_URL = "http://myurl/";
public static APIService getAPIService() {
return RetrofitClient.getClient(BASE_URL).create(APIService.class);
}
}
public class Login {
#SerializedName("username")
#Expose
private String username;
#SerializedName("password")
#Expose
private String password;
//getters and setters
}
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public class LoginActivity extends AppCompatActivity {
private EditText usernameEditText,passwordEditText;
private Button button;
private APIService mAPIService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
usernameEditText=(EditText)findViewById(R.id.username);
passwordEditText=(EditText)findViewById(R.id.password);
button=(Button)findViewById(R.id.signup);
mAPIService = ApiUtils.getAPIService();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String uname=usernameEditText.getText().toString();
String pass=passwordEditText.getText().toString();
if(TextUtils.isEmpty(uname)){
Toast.makeText(LoginActivity.this, "Username cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(TextUtils.isEmpty(pass)){
Toast.makeText(LoginActivity.this, "Password cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(pass.length()<4){
Toast.makeText(LoginActivity.this, "Password should be greater than four characters", Toast.LENGTH_SHORT).show();
return;
}
sendPost(uname, new StringBuilder(uname).reverse().toString());
}
});
}
public void sendPost(String username, String password) {
mAPIService.savePost(username, password).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
public void showResponse(String response) {
Log.i("Abbu",response);
}
}
Whenever i submit username and password i get null values,can some body please help me?And how can iget the sessionId.I tried looking for various egs but i am so confsued right now.
Instead of follwing code
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
Use this code
#POST("/authenticate")
Call<Login> savePost(#Query("username") String username,
#Query("password") String password);
Step 1: instead of this code
public interface APIService {
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
}
Use this code:
public interface APIService {
#POST("/authenticate")
Call<Login> savePost(#Body RequestBody body);
}
Step 2: instead of this code in LoginActivity
public void sendPost(String username, String password) {
mAPIService.savePost(username, password).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
Change to this code :
public void sendPost(String username, String password) {
HashMap<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
String strRequestBody = new Gson().toJson(params);
//create requestbody
final RequestBody requestBody = RequestBody.create(MediaType.
parse("application/json"),strRequestBody);
mAPIService.savePost(requestBody).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
Replace your Login class by following
#SerializedName("result")
#Expose
private String rESULT;
#SerializedName("response")
#Expose
private String response;
public String getRESULT() {
return rESULT;
}
public void setRESULT(String rESULT) {
this.rESULT = rESULT;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
Add ServiceGenerator class :
public class ServiceGenerator {
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(BASEURL)
.addConverterFactory(ScalarsConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
public static Retrofit getRetrofit()
{
return builder.client(httpClient.build()).build();
}
}
2.Add interface RetrofitAPI :
public interface RetrofitApi {
#POST("/api/v1/user")
Call<ResponseBody> login(#Body RequestBody loginBody);
}
3.Add method for login in your manager class :
public void retrofitLogin(JSONObject login, final String tag) {
RetrofitApi service = ServiceGenerator.createService(RetrofitApi.class);
Call<ResponseBody> result = service.login(convertJsonToRequestBody(login));
result.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
retrofitCheckResponse(response, tag);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if (t instanceof IOException) {
Log.e("retrofit error", "retrofit error");
sendErrorRetrofit(mContext.getString(R.string.ERROR), 500, tag);
}
}
});
}
Method to convert JSONObject to RequestBody :
private RequestBody convertJsonToRequestBody(JSONObject jsonObject) {
if (jsonObject != null) {
return RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), jsonObject.toString());
} else {
return null;
}
}
4.Now call your retrofitLogin method :
JSONObject mLoginParams = new JSONObject();
JSONObject mLoginObj = new JSONObject();
mLoginParams.put("username", uname);
mLoginParams.put("password", pass);
mLoginObj.put("appType","mobile");
mLoginObj.put("user", mLoginParams);
volleyRequest.retrofitLogin(mLoginObj, "Login");
In my android app i have done Facebook integration.Facebook login works fine.How can i get user's email id from Facebook integration in android?
please help.
thanks in advance.
Use permission and this code
loginButton.setReadPermissions(Arrays.asList( "email","user_birthday"));
and use Graph Api
private FacebookCallback<LoginResult> mCallBack = new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
progressDialog.dismiss();
// App code
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(
JSONObject object,
GraphResponse response) {
Log.e("response: ", response + "");
Log.e("object: ", object + "");
try {
userfbData = new UserfbData();
userfbData.facebookID = object.getString("id").toString();
userfbData.email = object.getString("email").toString();
userfbData.name = object.getString("name").toString();
userfbData.gender = object.getString("gender").toString();
userfbData.birthday=object.getString("birthday").toString();
PrefUtils.setCurrentUser(userfbData,LoginActivity.this);
Log.d("flist","flist"+ userfbData.flist);
}catch (Exception e){
e.printStackTrace();
}
// Toast.makeText(LoginActivity.this,"welcome "+userfbData.name+userfbData.email+userfbData.gender+userfbData.birthday, Toast.LENGTH_LONG).show();
Toast.makeText(LoginActivity.this,"welcome "+ userfbData.name, Toast.LENGTH_LONG).show();
Intent intent=new Intent(LoginActivity.this,LogoutActivity.class);
startActivity(intent);
finish();
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender, birthday");
request.setParameters(parameters);
request.executeAsync();
}
#Override
public void onCancel() {
progressDialog.dismiss();
}
#Override
public void onError(FacebookException e) {
progressDialog.dismiss();
Log.d("error","error"+e);
e.printStackTrace();
}
};
UserFbData
public class UserfbData {
public String name;
public String email;
public String facebookID;
public String gender;
public String birthday;
}
You need to make a GraphRequest call to get personal information of the logged in user such as id, name, email etc.
GraphRequest request = GraphRequest.newMeRequest(accessToken,
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
try {
String email = object.getString("email");
} catch (JSONException e) {
}
}
}
);
Bundle parameters = new Bundle();
parameters.putString("fields","email");
request.setParameters(parameters);
request.executeAsync();
//code
callback = new FacebookCallback<LoginResult>() {
Profile profile;
#Override
public void onSuccess(LoginResult loginResult) {
profile = Profile.getCurrentProfile();
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
// Application code
try {
email=object.getString("email");
login(email,profile.getId());
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "email");
request.setParameters(parameters);
request.executeAsync();
nextActivity();
}
#Override
public void onCancel() {
}
#Override
public void onError(FacebookException e) {
}
};
public void login(String email,String password){
editor.putBoolean("islogin",true);
editor.putString("email", email);
editor.putString("password",password);
editor.commit();
}
I want to get email from FacebookCallback but the login method doesn't execute and when I try to use email(variable) out of the callback I get the first value of email?? how can I solve this problem !! thanks
Since the email variable wasn't in the code snippet it must have come from outside of the nested anonymous functions: new FacebookCallback<LoginResult>() and new GraphRequest.GraphJSONObjectCallback() Which means it would have had to been declared final and so the value couldn't have been reset in your code: email=object.getString("email");
You should use a local variable instead:
try {
String userEmail =object.getString("email");
login(userEmail,profile.getId());
}