How to convert cURL to retrofit correct form? - java

Sorry for my English. I want use this service. For determine the language of the text.
Request(Curl):
curl -X POST -d "outputMode=json" --data-urlencode text#ibm.txt -d "url=http://www.ibm.com/us-en/" "https://gateway-a.watsonplatform.net/calls/text/TextGetLanguage?apikey=%API_KEY%"
I use Retrofit for request.
public interface LanguageDetectionApi {
public static final String ROOT_URL = "https://gateway-a.watsonplatform.net/calls/";
#POST("/text/TextGetLanguage")
Call<List<PostModel>> getData(#Query("apikey") String apikey, #Query("text") String text);
}
Create retrofit object:
public class App extends Application {
private static LanguageDetectionApi _languageDetectionApi;
private Retrofit _retrofit;
#Override
public void onCreate() {
super.onCreate();
_retrofit = new Retrofit.Builder()
.baseUrl(_languageDetectionApi.ROOT_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
_languageDetectionApi = _retrofit.create(LanguageDetectionApi.class);
}
public static LanguageDetectionApi getLanguageDetectionApi() {
return _languageDetectionApi;
}
}
And send request:
App app = new App();
app.onCreate();
app.getLanguageDetectionApi().getData("4978e60252ae102dfe1341146bb8cc3ec4bbbd78", textForRecognition).enqueue(new Callback<List<PostModel>>() {
#Override
public void onResponse(Call<List<PostModel>> call, Response<List<PostModel>> response) {
List<PostModel> posts = new ArrayList<>();
posts.addAll(response.body());
}
#Override
public void onFailure(Call<List<PostModel>> call, Throwable t) {
Toast.makeText(MainActivity.this, "An error occurred during networking", Toast.LENGTH_SHORT).show();
}
});
PostModel i generated in site http://www.jsonschema2pojo.org/.
Questions:
No response comes to me, although apikey are exactly valid.
How to specify in the interface parametr "outputMode=json"?
And I translated correctly cURL to LanguageDetectionApi?
It seems to me that the whole mistake in the class LanguageDetectionApi. Can you help deal with this? Thank you!

change url code like below:
public interface LanguageDetectionApi {
public static final String ROOT_URL = "https://gateway-a.watsonplatform.net";
#POST("/calls/text/TextGetLanguage")
Call<List<PostModel>> getData(#Query("apikey") String apikey, #Query("text") String text);
}
base url should be ony host name.

Related

Retrofit POST Request with body parameters android

I need to execute post request with retrofit but i have a problem which i can't understand very well. Before trying with code i tested api call with Postman and request look like this:
Here is my android code:
public class API {
private static <T> T builder(Class<T> endpoint) {
return new Retrofit.Builder()
.baseUrl(Utils.API_BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(endpoint);
}
public static AllRequests request() {
return builder(AllRequests.class);
}
}
EDIT request:
#POST("api/android-feedback")
#Headers({"Content-Type: application/x-www-form-urlencoded", "Authorization: F##3FA##Rad!#%!2s"})
Call<String> sendFeedback(#Body FeedbackBody body);
FeedbackBody:
public class FeedbackBody{
private final String email;
private final String feedback;
public FeedbackBody(String email, String feedback){
this.email = email;
this.feedback = feedback;
}
}
And finally i construct the request and wait for response, the problem is that i receive message in onFail method
private void sendFeedbackRequest(){
API.request().sendFeedback(new FeedbackBody("testmeil#meil.com", "test feedback").enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
goToMainActivity();
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(SplashScreenActivity.this, R.string.try_again_later, Toast.LENGTH_SHORT).show();
}
});
EDIT:
Still not working.. i think i figure it out where can be the problem, because server side wait for simple POST request without Json formatting, i think Retrofit use JSON formatting by default, and if i send POST request and format Body parameters with JSON the server will fail to parse my request, is there any chance to send simple POST request like at POSTMAN without formatting with JSON ?
Php api wait request to be send like this:
$_POST['feedback'] = 'blabla';
$_POST['email'] = 'blabla..';
and if he receive Json format request can't parse it and because of that i receive fail response.
First you need to create request( POJO Class)
public class FeedbackRequest {
public String email;
public String feedback;
}
when you call sendFeedbackRequest() pass the FeedbackRequest like below"
FeedbackRequest req = new FeedbackRequest();
req.email= "email";
req.feedback= "feedback"
sendFeedbackRequest(req)
after that your sendFeedbackRequest() should be like this
private void sendFeedbackRequest(FeedbackRequest request){
API.request().sendFeedback(request).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
goToMainActivity();
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(SplashScreenActivity.this, R.string.try_again_later, Toast.LENGTH_SHORT).show();
}
});
And your retrofit request should be like this,
#FormUrlEncoded
#POST("api/android-feedback")
#Headers({"Content-Type: application/json", "Authorization: F31daaw313415"})
Call<String> sendFeedback(#Body FeedbackRequest request);
Now it should work. feel free to ask anything.
You are using a Gson converter factory. It might be easier to create a single object that represents your body, and use that instead of all individual parameters. That way, you should be able to simple follow along with the examples on the Retrofit website.enter link description here
There are also many site that let you generate your Plain Old Java Objects for you, like this one:
E.g. your Api call:
#POST("api/android-feedback")
Call<String> sendFeedback(#Body FeedbackBody feedback);
And your FeedbackBody class:
public class FeedbackBody{
private final String email;
private final String feedback;
public FeedbackBody(String email, String feedback){
this.email = email;
this.feedback = feedback;
}
}
Java:
#POST("/api/android-feedback")
Call<String> sendFeedback(#Body FeedbackBody feedback);
Kotlin:
#POST("/api/android-feedback")
fun sendFeedback(#Body feedback: FeedbackBody): Call<String>
Also, probably you forgot leading slash in the endpoint.
val formBody: RequestBody = FormBody.Builder()
.add("username", LoginRequest.username)
.add("password", LoginRequest.password)
.add("grant_type",LoginRequest.grant_type)
.add("client_id", LoginRequest.client_id)
.add("client_secret", LoginRequest.client_secret)
.add("cleartext", LoginRequest.cleartext)
.build()
#POST(EndPoints.GENERATE_TOKEN_URL)
#Headers("Content-Type: application/x-www-form-urlencoded")
suspend fun getLogin(
#Body formBody: RequestBody
): LoginResponse

unknown issue in using Retrofit 2

I am new to Android and I want to make an application based on REST API.
So I search and found the Retrofit 2.
I used a sample of retrofit that I found in Github to learn how it works.
This files are my Java classes :
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textv = findViewById(R.id.textv);
GitHubClient gitHubClient;
gitHubClient = ServiceGenerator.createService(GitHubClient.class);
final Call<GitHubUser> call = gitHubClient.getFeed("google");
call.enqueue(new Callback<GitHubUser>() {
#Override
public void onResponse(Call<GitHubUser> call, Response<GitHubUser> response) {
GitHubUser gitModel = response.body();
if (gitModel != null) {
textv.setText(getString(R.string.main_response_text,
gitModel.getName(),
gitModel.getBlog()));
} else {
textv.setText("user doesn't exist");
}
}
#Override
public void onFailure(Call<GitHubUser> call, Throwable t) {
textv.setText(t.getMessage());
}
});
}
}
GithubClient.java
public interface GitHubClient {
#GET("users/{user}")
Call<GitHubUser> getFeed(#Path("user") String user);
}
ServiceGenerator.java
public class ServiceGenerator {
public static final String API_BASE_URL = "https://api.github.com/";
private static HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
private static Interceptor logging = interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
private static OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient).build();
return retrofit.create(serviceClass);
}
}
GithubUser.java
public class GitHubUser {
private String name;
private String blog;
public String getName() {
return name;
}
public String getBlog() {
return blog;
}
}
JSON code from Github
{
...
"name": "Google",
"blog": "https://opensource.google.com/",
...
}
I want to get the name and blog URL
And when I run the program the output is:
javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb8952b10: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version(external/openssl/ssl/s23_clnt.c:741 0x83bc3770:0x00000000)
What's the problem and how can I fix?
The first step here would be to understand the error.
Try printing the error from your onFailure method like this:
#Override
public void onFailure(Call<GitHubUser> call, Throwable t) {
textv.setText("unknown error"); // can also do textv.setText(t.getMessage()) to display error reason
t.printStackTrace();
}
You should get in your logcat some more useful information about what went wrong, it will be easier to figure out how to solve it after that
Also have you added internet access permission in your manifest?
SSL Exception comes when SSL Certificate issue . You need to add ssl certificate to server side.
Have you tried
android:networkSecurityConfig="#xml/network_security_config"
in your manifest tag
also put the following file in res >> xml >>
network_security_config.xml
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">static.food2fork.com</domain>
</domain-config>
</network-security-config>

Getting Internal Server Error 500 in Retrofit

I know there are a lot of threads regarding this and i did go through them and also looked into the same Retrofit POST example,but i'm not sure what am i doing wrong in this,lemme know if any
#Multipart
#POST("api/customerdetail")
Call<Array> addUser(#Part("CustomerName") String CustomerName, #Part("CustomerId") String CustomerId, #Part("UserId") String UserId, #Part("VehicleCompanyName") String VehicleCompanyName, #Part("VehicleModelType")String VehicleModelType, #Part("VehicleNumber")String VehicleNumber, #Part("Location")String Location);
//METHOD USED TO CALL
private void simpleMethod() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://endpoint.net/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GetDataService service = retrofit.create(GetDataService.class);
Call<Array> arrayListCall = service.addUser("Peter Jenkins", UUID.randomUUID().toString(),"user2","AUDI","R3","BVZ-009","-55,-93.23"); arrayListCall.enqueue(new Callback<Array>() {
#Override
public void onResponse(Call<Array> call, Response<Array> response) {
Log.e("RESPONSE",response.toString());
}
#Override
public void onFailure(Call<Array> call, Throwable t) {
Log.e("ERROR",t.toString());
} }); }
Works like a Charm in Postman,and uploading an image is not necessary,atleast from the api end
Any inputs would be deeply appreciated

Retrofit2 - having issues sending POSt request to API

I would really really appreciate any help I can get on this! Sorry for the long question.
I'm creating this android app, where to sign up, users will type in their phone number and submit it, to get a verification code via text message.
I have worked off of this tutorial:
https://code.tutsplus.com/tutorials/sending-data-with-retrofit-2-http-client-for-android--cms-27845
I have reduced the 2 fields in their app to one field - one text field for a phone number, and a submit button below. This phone number is to be sent to the API.
I'm really new to Retrofit, and I've been trying for a while now to successfully send a call to the API. I have tested the API call by using the 'Postman' desktop app, and the API is alive and responding...I've just not been able to form a valid request to send to the API.
The JSON schema our API guy designed...for this activity needs just one string, the phone number:
{
"phone_number": "string"
}
and then if it is a valid phone number and the user isn't in the database, you get back a 200 response
{
"message": "string"
}
OR you can get back a 400 response from the API
{
"error": "string",
"description": "string"
}
My retrofit interface, called APIService.java looks like this:
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.Body;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface APIService {
#POST("/verifications/signup/send")
#FormUrlEncoded
Call<Post> sendPhoneNumber(#Field("phone_number") String phone_number);
}
I am really new to retrofit2, and above, I can sense one issue, which I don't know how to solve. From the API schema I was given, this one parameter I sent to the API should be 'body'....not 'field'. Maybe in retrofit #Body...I am not too sure how to implement that in this java file above.
Now, what I did below might be really stupid...I don't understand how retrofit java 'model' classes should be made. I followed one tutorial that modeled the class after the RESPONSE, rather than the data call. So, I modified their Post class (which is what I called my ?JSON object to send a single phone number). So my Post class looks like this:
public class Post {
#SerializedName("message")
#Expose
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
#Override
public String toString() {
//return "Post{" + "message = " + message + '}';
return "This is a return message string";
}
}
Honestly, I think what I've done might be totally wrong, but I am not sure how to design the object(Post) class, considering I don't even know what this class will be used for...except getting the response back?
public class MainActivity extends Activity {
private TextView mResponseTv;
private APIService mAPIService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText phoneNumberEt = (EditText)
findViewById(R.id.et_phoneNumber);
Button submitBtn = (Button) findViewById(R.id.btn_submit);
mResponseTv = (TextView) findViewById(R.id.tv_response);
mAPIService = ApiUtils.getAPIService();
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String phoneNumber = phoneNumberEt.getText().toString().trim();
if (!TextUtils.isEmpty(phoneNumber)) {
sendPost(phoneNumber);
}
}
});
}
public void sendPost(String phone_number) {
mAPIService.sendPhoneNumber(phone_number).enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response) {
int statusCode = response.code();
if (response.isSuccessful()) {
showResponse("Response code is " + statusCode + ". Submitted successfully to API - " + response.body().toString());
Log.i(TAG, "post submitted to API." + response.body().toString());
}
}
#Override
public void onFailure(Call<Post> call, Throwable t) {
showResponse("Unable to submit post to API.");
Log.e(TAG, "Unable to submit post to API.");
}
});
}
public void showResponse(String response) {
if (mResponseTv.getVisibility() == View.GONE) {
mResponseTv.setVisibility(View.VISIBLE);
}
mResponseTv.setText(response);
}
}
My other files are pretty much exactly like the files in the tutorial link above. That's what I modified to get to my simple one text field version.
When I am able to get this to contact the API, and I can read the response, then I'll incorporate this into the real app I'm working on.
For now, the app compliles, and runs on my phone(and emulator too). When I submit the phone number, the text field below the submit button doesn't show any message like it should...so I know for sure that theres a problem once
mAPIService.sendPhoneNumber(phone_number).enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response)
{
is reached in MainActivity.
I think that this api requires parameters in JsonObject. so try this
In your APIService
#POST("/verifications/signup/send")
Call<JsonObject> sendPhoneNumber(#Body JsonObject phone_number);
And when sending data use this
JsonObject object=new JsonObject();
object.addProperty("phone_number",yourPhoneNumber);
and in your send post method
mAPIService.sendPhoneNumber(object).enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
int statusCode = response.code();
if (response.isSuccessful()) {
showResponse("Response code is " + statusCode + ". Submitted successfully to API - " + response.body().toString());
Log.i(TAG, "post submitted to API." + response.body().toString());
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
showResponse("Unable to submit post to API.");
Log.e(TAG, "Unable to submit post to API.");
}
});
}
Please try and let me know if it is working.
According to the JSON schema with the phone number, you need to pass the phone number in the body of the API. Instead of using a #Field annotation, use a #Body annotation where the parameter will be an instance of the RequestBody class.
#Field documentation https://square.github.io/retrofit/2.x/retrofit/retrofit2/http/Field.html
Create the new RequestBody class with field phone number.
public class RequestBody {
#Expose
#SerializedName("phone_number")
private String phoneNumber;
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPhoneNumber() {
return phoneNumber;
}
From the activity when you want to pass the phone number, create an object of the RequestBody class, pass the phone number in the setPhoneNumber() method. Then pass this object in the APIService as a parameter.
In MainActivity.class,
public void sendPost(String phone_number) {
RequestBody requestBody = new RequestBody();
requestBody.setPhoneNumber(phone_number);
mAPIService.sendPhoneNumber(requestBody).enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response)
{
Your APIService will thus look like
public interface APIService {
#POST("/verifications/signup/send")
#FormUrlEncoded
Call<Post> sendPhoneNumber(#Body RequestBody requestBody);
}

Where to insert API key into POST request in Android studio

Just want to know where do I insert the API key for the server in my code below:
public class GetCurrentJob extends Job {
Context context;
GetFeedback feedback;
protected GetCurrentJob(Context context, GetFeedback fb) {
super(new Params(PRIORITY.HIGH).requireNetwork());
feedback = fb;
this.context = context;
}
#Override
public void onAdded() {
}
#Override
public void onRun() throws Throwable {
//POST feedback to server... require API key. How?
Response<String> response = Ion.with(context)
.load("POST", URLbuilder.getURL())
.setStringBody(feedback.toJson())
.asString()
.withResponse()
.get();
//Toast.makeText(context, "post", Toast.LENGTH_SHORT).show();
if (response.getHeaders().code() != HttpURLConnection.HTTP_OK) {
Log.d("test", "error in request " + String.valueOf(response.getResult()));
return;
}
else
{
Log.d("test", "success" + String.valueOf(response.getResult()));
}
}
#Override
protected void onCancel(int cancelReason, #Nullable Throwable throwable) {
}
#Override
protected RetryConstraint shouldReRunOnThrowable(#NonNull Throwable throwable, int runCount, int maxRunCount) {
return null;
}
}
My URLbuilder class:
public class URLbuilder {
private static final String SERVER = "http://jxapp-s-ticket.cloudapp.net/jxapp_ticket/upload/api/http.php/tickets.json";
public static String getURL(){
return Uri.parse(SERVER).buildUpon().toString();
}
}
Just a little information:
My app takes user feedback and returns the feedback to the server, then the server will generate a ticket to the user.
I am able to generate a response from the server, namely from the log. But the log generates: "error in request Valid API key required".
I need a way to insert the API key but I do not know how (am quite new to Android Studio as well as POST and GET operations)!
Do help if possible! Thanks!
Response<String> response = Ion.with(context)
.load("POST", URLbuilder.getURL())
.setHeader("x-api"," API KEY HERE ")
.setStringBody(feedback.toJson())
.asString()
.withResponse()
.get();
Should anyone encounter the same problem this is how i solved this.
Modified the ion formatting by adding a header with the API key.
All credits to a senior of mine.

Categories