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.
Related
I calling to the api with the basic retrofit Call object:
public interface dataApi {
#GET("animal/cats")
Call<AllAnimals> getAllData(
#Query("api_key") String apiKey
);
}
And I can get the response inside my view model like this:
call.enqueue(new Callback<AllAnimals>() {
#Override
public void onResponse(Call<AllAnimals> call, Response<AllAnimals> response) {
animals.setValue(response.body());
}
#Override
public void onFailure(Call<AllAnimals> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
Nothing speical here.
I've several problem with this approach
FIRST - if I give the wrong api key for example, the response should give me a response with the code of the problem, instead I just get null body.
SECOND I am planning to have more api calls, and it's a huge code duplication to handle errors every call I wrote.
How can I implement custom error handling for this situation, that will be apply to other calls too?
I think you can use okhttp interceptor and define yourself ResponseBody converter to fix your problem.
First,intercept you interested request and response;
Second,check the response,if response is failed then modify the response body to empty。
define a simple interceptor
Interceptor interceptor = new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String url = request.url().toString();
System.out.println(request.url());
okhttp3.Response response = chain.proceed(request);
if (!response.isSuccessful() && url.contains("animal/cats")) {
// request failed begin to modify response body
response = response.newBuilder()
.body(ResponseBody.create(MediaType.parse("application/json"), new byte[] {}))
.build();
}
return response;
}
};
define self ResponseBody converter
most code from com.squareup.retrofit2:converter-jackson we just add two lines:
final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final ObjectReader adapter;
JacksonResponseBodyConverter(ObjectReader adapter) {
this.adapter = adapter;
}
#Override public T convert(ResponseBody value) throws IOException {
try {
if (value.contentLength() == 0) {
return null;
}
return adapter.readValue(value.charStream());
} finally {
value.close();
}
}
}
the below code is added:
if (value.contentLength() == 0) {
return null;
}
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);
}
I want to read arraylist from android into php in order to store in database, but I'm not able to find exact code for it. Can anybody guide me in the direction to solve this problem ?
Here is my java code for creating the arraylist
private void loadCart()
{
productList.clear();
Cursor cursor = dbHelper.getCarProducts();
cursor.moveToFirst();
do {
CartProduct cartProduct = new CartProduct();
cartProduct.setProductName("Name: "+cursor.getString(cursor.getColumnIndex("_Name")));
cartProduct.setProductCost("Cost: "+cursor.getString(cursor.getColumnIndex("_Cost")));
cartProduct.setProductPrice("Price: "+cursor.getString(cursor.getColumnIndex("_Price")));
cartProduct.setProductQuantity("Quantity: "+cursor.getString(cursor.getColumnIndex("_Quantity")));
productList.add(cartProduct);
}while(cursor.moveToNext());
}
I'm using retrofit2 in order to send the arraylist to the server, but as I have seen in other question here I'm not able to get the url for the file_get_contents ?
Here you go...
Step 1: Add retrofit dependency in your gradle.app
compile 'com.squareup.retrofit:retrofit:1.9.0'
Step 2: Make an RestClient class like below.
public class RestClient {
private static final String BASE_URL = DataConstants.TEST_URL; //Place your web service URL here
private ApiInterface apiService;
public RestClient()
{
RequestInterceptor requestInterceptor = new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json");
}
};
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setRequestInterceptor(requestInterceptor)
.setEndpoint(BASE_URL)
.build();
apiService = restAdapter.create(ApiInterface.class);
}
public ApiInterface getApiService()
{
return apiService;
}
}
Step 3: Make an Interface for POST URL.
public interface ApiInterface {
#POST("/sendData")
void sendData(#Body JsonObject jsonObject,
Callback<DataModel> dataModelCallback);
}
Step 4: Make an POJO class like below.
public class DataModel{
private String success;
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
}
Step 5: Make an call of webservice from your activity like below.
private void callWebService(String user_id) {
try {//TODO SEND
final Utility utility = new Utility(this);
utility.showProgressDialog();
JsonObject myJsonData = new JsonObject();
myJsonData.addProperty("user_id", user_id);
Gson gsonData = new GsonBuilder().create();
JsonArray dataArray = new JsonArray();
dataArray = gsonData.toJsonTree(productList).getAsJsonArray(); //Here you want to add your array list i.e productList
myJsonData.add("assign_to", jaAssignee);
new RestClient().getApiService().sendData(myJsonData, new Callback<DataModel>() {
#Override
public void success(DataModel dataModel, Response response) {
utility.hideProgressDialog();
try {
String success = dataModel.getSuccess();
if (success.equalsIgnoreCase("Success")) {
//Do what you want to do
}
} catch (Exception e) {
}
}
#Override
public void failure(RetrofitError error) {
utility.hideProgressDialog();
}
});
} catch (Exception e) {
}
}
Hope this will help you!
Send all your data in one go. Create JsonArray and add each object by creating JsonObject. After its done upload all the data in one go. You'll just have to decode that array in php.
Advantage of using this is, you can manage the response in retrofit very well (being it asynchronous)
you can parse json value in php by
<?php
header('Content-type: application/json');
$jsonString = file_get_contents('php://input');
$jsonArray = json_decode($jsonString,true);
print_r($jsonArray);/* print array */
?>
After almost searching for 3+ weeks and n+ hours of frustration, i've finally found an working solution to my problem and sharing it with people so they could benefit from it (as i was blocked from another a/c due to asking too many questions and down votes ) , in order to send your array list to your server we need to use another library and the best fit according to my need is async-http library by loop j and these are the steps to import and use the library in your program :-
1.)import the library into your project by writing this statement in your bulid.gradle(app module):-
compile 'com.loopj.android:android-async-http:1.4.9'
2.)Create the following variables in order to use them in your program:-
AsyncHttpClient (a client to send data to your server)
RequestPrarms (Data sent to your server for parsing and further operations )
String url(Link to your server where actually operations occurs)
3.) Now we use these variables and run the program :-
p
arams.put("OrderSummary", <your array list>);
httpClient.post(APIURL.API_URL,params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
//your operations on success
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Toast.makeText(getApplicationContext(),error.toString(),Toast.LENGTH_LONG).show();
}
});
i hope this clears your doubts somewhat i'm still creating my php side in order to insert data in the database
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.
Hi folks I'm creating an android application's login/register part using the Android Volley Library. My application was working well, but the UI and logic were at the same class. So, I have separated them into two classes. My app makes requests to my NodeJS server using POST methods and gets JSON response. So I have tried to keep the POST request function in another class.
After separating the classes, I have a problem while waiting for response. Here is the function;
public String doWebRequestLogin(Context context, boolean checkLoginForm, final Map<String,String> json){
result[0] = "FREE";
this.context = context;
if(checkLoginForm){
StringRequest post = new StringRequest(Request.Method.POST, loginUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
Log.d("Login Response: ",response);
data = response;
res = new JSONObject(data);
if (res.getString(KEY_SUCCESS) != null) {
int success = Integer.parseInt(res.getString(KEY_SUCCESS));
if (success == 1) {
result[0] = "LOGGED";
} else if (success == 0) {
result[0] = "LOGIN ERROR";
} else {
result[0] = "INVALID POST";
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Response Error", error.toString());
result[0] = "INVALID POST";
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> map = json;
return map;
}
};
VolleyController.getInstance(this.context).getRequestQueue().add(post);
}
return result[0];
}
This function returns result[0] as "FREE" at every time due to response time. How could it wait for the response and set result[0] according to the response? I need to know what happened while making requests.
I'm calling doWebRequestLogin() on the UI within an onclick function
Then you do NOT want to "wait for the response". That will freeze your UI for however long the network I/O takes, and your users will... be unimpressed.
Instead, update your UI in the onResponse() and onErrorResponse() methods.
This sort of asynchronous call, handling the results via callbacks, is core to the event-driven programming model at the heart of Android.
The request is asynchronous and you must not block the main thread waiting for a response. Make the method void and use a callback to handle the response once it's received.
public void doWebRequestLogin(SomeCallback callback, Context context, boolean checkLoginForm, final Map<String,String> json){
[...]
if (res.getString(KEY_SUCCESS) != null) {
int success = Integer.parseInt(res.getString(KEY_SUCCESS));
callback.someMethod(success);
}
}
For the callback:
public interface SomeCallback{
void someMethod(int result); // response received, handle it
}
Callback may also have a return type or be generic, this depends solely on your needs...