I am trying to make an app that will list all github repos public/private of a user via github REST API.
Here is GithubService for retrofit.
public interface GithubService {
#GET("user")
Call<User> getUser(#Header("Authorization") String authHeader);
#GET("users/{user}/repos")
Call<List<GitHubRepo>> userRepos(#Header("Authorization") String authHeader, #Path("user") String userId);}
I have a login form which takes in username and user's personal access token as password and here is the code that I use for requesting user info, this returns valid user info:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.client(clientBuilder.build())
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
GithubService service = retrofit.create(GithubService.class);
String cred = Credentials.basic(username, password);
service.getUser(cred).enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
Log.d(TAG, "onResponse: " + response.isSuccessful());
fetchRepos(password, response.body());
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage());
}
});
in fetchRepos I am trying to use the personal access token as auth header for requesting user repos but it returns null, here is the code:
private void fetchRepos(String pat, User user) {
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.client(clientBuilder.build())
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
GithubService service = retrofit.create(GithubService.class);
service.userRepos(pat, user.getLogin()).enqueue(new Callback<List<GitHubRepo>>() {
#Override
public void onResponse(Call<List<GitHubRepo>> call, Response<List<GitHubRepo>> response) {
Log.d(TAG, "onResponse: " + response.isSuccessful());
}
#Override
public void onFailure(Call<List<GitHubRepo>> call, Throwable t) {
}
});
}
Where am I wrong here? How to continue with authorization to request user repos and how is Two-Factor code integrated into authorization?
Github OAuth V3 required Web-based Authentication, You can try this SDK, It will reduce your boilerplate code and returns proper Auth Token for Github. And it's lightweight, no extra packages required.
SDK Link: https://github.com/debojyoti452/GithubLoginSDK
Related
I'm using retrofit to connect APIs. It is working fine when fetching data from https API but getting response "Null" and error body response "okhttp3.ResponseBody$1#174390c" when fetching data from http API.
Here is the Retrofit client class:
public static Retrofit getSClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
}
return retrofit;
}
Here is the Apiservice Class:
#GET("Mobile/OperatorFetch?")
Call<String>getOperatorDetails(#Query("apimember_id")String apiMemberId,
#Query("api_password")String apiPassword,
#Query("Mobileno")String mobileNumber);
Here is the ApiUtils Class:
public static ApiService getSApiService(){
return RetrofitClient.getSClient(PLAN_URL).create(ApiService.class);
}
Here is my network request method from Repository class:
private void fetchOperator(String apiId, String apiPassword, String mobile) {
ApiService apiService = ApiUtills.getSApiService();
apiService.getOperatorDetails(apiId, apiPassword, mobile)
.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful() && response.body() != null){
Log.e(TAG,"Operator fetch successful: " + response.body().toString());
}else {
Log.e(TAG,"Operator fetch failed: " + response.errorBody().toString());
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG,"Fetch operator failed" + t.getMessage());
}
});
}
Getting response from Post Man
In my application, I connect to a server and have to get a successful response to my further working, after such type of response, in general, I get two tokens ( access+refresh). For my further actions, I have to use my access token because I won't be able to get data. This token, in general, expires in 30 minutes. I can't understand how I can get a new token from the server without fails of my application. I had seen some questions and this Refreshing OAuth token using Retrofit without modifying all calls one was the best I think. But I can't understand the way of using it for me.
Right now I am using such an interface:
public interface APIService {
#Headers("Content-type: application/json")
#POST("/v1/login")
Call<Post> auth(#Body Post body);
#Headers({"Content-type: application/json",
"Authorization: Bearer access_token"})
#GET("/v1/message/list")
Call<Message> getInMess(#Query("type") int type, #Query("offset") int offset);
}
there I have to insert my access token by hands.
And then in my MainActivity Class I initialize my interface:
public void sendPost()
{
final EditText titleEt = findViewById(R.id.login);
final EditText bodyEt = findViewById(R.id.password);
final String a = titleEt.getText().toString().trim();
final String b = bodyEt.getText().toString().trim();
saveData();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://server/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
APIService mAPIService = retrofit.create(APIService.class);
//retrofit.create(APIService.class);
mAPIService.auth(new Post(a, b)).enqueue(new Callback<Post>() {
#Override
public void onResponse(#NonNull Call<Post> call, #NonNull Response<Post> response) {
if (response.isSuccessful()) {
Toast.makeText(LoginActivity.this, "Post submitted to API.", Toast.LENGTH_LONG).show();
Intent intent = new Intent(LoginActivity.this, SecondScreen.class);
findViewById(R.id.btn_submit).getBackground().setColorFilter(Color.parseColor("#1cd000"), PorterDuff.Mode.MULTIPLY);
startActivity(intent);
} else {
Toast.makeText(LoginActivity.this, "Unable to submit post to API.Error!!!", Toast.LENGTH_LONG).show();
findViewById(R.id.btn_submit).getBackground().setColorFilter(Color.parseColor("#FF0000"), PorterDuff.Mode.MULTIPLY);
}
}
#Override
public void onFailure(#NonNull Call<Post> call, #NonNull Throwable t) {
Toast.makeText(LoginActivity.this, "Unable to submit post to API.", Toast.LENGTH_LONG).show();
}
});
}
Please help me to understand the strategy of my further development because I can't solve my problem.
P.S. Sorry for my bad English))
You need to intercept the request and add the header in your interceptor. I use this in my applications :
public class AuthenticationInterceptor implements Interceptor {
public AuthenticationInterceptor(Context context) {
}
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if(!YOUR_TOKEN.isEmpty()) {
Request authenticatedRequest = request.newBuilder().header("Authorization", "Bearer:" + YOUR_TOKEN).build();
return chain.proceed(authenticatedRequest);
}
return chain.proceed(request);
}
}
I am creating a simple log-in/register app, consuming predefined JSON-structured data. So far I have created the GET endpoint (using retrofit)
public interface RetrofitGet {
#GET("----")
Call<User> getUserDetails();
}
EDIT: the POST endPoint:
#POST("----")
Call<User> postUserDetails();
Then I have a method, taking the entered JSON-like data and set the data as text of 2 of the fields:
private void getUser() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitGet service = retrofit.create(RetrofitGet.class);
Call<User> call = service.getUserDetails();
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Response<User> response, Retrofit retrofit) {
try {
input_email.setText(response.body().getEmail());
input_pass.setText(response.body().getPassword());
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
Log.d("onFailure", t.toString());
}
});
What I am trying to do now is to define the POST endpoint, in order to be able the data to be generated from the app (to be taken from the register form), posted on the server, and then handled in the login.
EDIT:
The method, consuming the POST endpoint so far:
private void postUser() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitPost service = retrofit.create(RetrofitPost.class);
Call<User> call = service.postUserDetails();
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Response<User> response, Retrofit retrofit) {
try {
emailRegister.getText().toString();
passRegister.getText().toString();
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
So, I have the data, entered by the user on Register, but I don't see it stored in the server and cannot handle it in the Login part.
Any help would be appreciated,
Thanks!
#POST("----")
Call<CommonBean> comment(#Body PostComment comment);
and the PostComment:
public class PostComment {
private int pcOrdersId;
private int pcStar;
private String pcComment;
public PostComment(int pcOrdersId, int pcStar, String pcComment) {
this.pcOrdersId = pcOrdersId;
this.pcStar = pcStar;
this.pcComment = pcComment;
}
}
others on different with 'GET'
Can anyone help me unit testing api calls using retrofit 2.0 and eventBus for managing the response from the api, Specifically using Robospock
public boolean login(String username, String password) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(EndpointInterface.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
EndpointInterface EndpointInterface = retrofit.create(EndpointInterface.class)
LoginData loginData = new LoginData(username, password)
Call<AunthenticatedUser> call = EndpointInterface.doLogin(loginData)
call.enqueue(new Callback<AunthenticatedUser>() {
#Override
void onResponse(Call<AunthenticatedUser> callAsync, Response<AunthenticatedUser> response) {
SuccessfulLoginEvent event = null
AunthenticatedUser user = response.body()
if (response.isSuccess()) {
Log.d("Body", "" + user)
if (user != null) {
}
}
event = new SuccessfulLoginEvent(user)
bus.postSticky(event)
}
#Override
void onFailure(Call<AunthenticatedUser> callAsync, Throwable t) {
Log.d("Error :", t.getMessage())
UnsuccessfulLoginEvent event = new UnsuccessfulLoginEvent(t.getMessage())
bus.post(event)
}
})
Probably a novice question but I'm wondering where I actually catch the logs in log cat. Is there a particular place I put a log, a special regex to use etc. This is what my interceptor looks like:
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okClient = new OkHttpClient.Builder().addInterceptor(interceptor).build();
// Retrofit setup
Retrofit client = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okClient)
.build();
And here is an api call where the body is null
retrofit2.Call<GeneralTokenResponse> generalTokenResponseCall = ApiInterface.getGeneralAccessToken(ApiGeneral.API_VERSION);
generalTokenResponseCall.enqueue(new retrofit2.Callback<GeneralTokenResponse>() {
#Override
public void onResponse(retrofit2.Call<GeneralTokenResponse> call, retrofit2.Response<GeneralTokenResponse> response) {
Log.d("DEBUG", "body: "+response.body());
}
#Override
public void onFailure(retrofit2.Call<GeneralTokenResponse> call, Throwable t) {
}
});
I use so:
// init okhttp 3 logger
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
#Override public void log(String message) {
Log.d("MyTAG", "OkHttp: " + message);
}
});
logging.setLevel(HttpLoggingInterceptor.Level.BODY);