Call Async a Restfull WebService in Android Java - java

I need to make a call to the webservice in android java and another class calls it. I the end, showing the ws response in UI.
I've done the webservice. Only that part of the "asynchronous" is not working properly.
This is my webservice, receiving three strings:
public class WebServiceRestFull extends AsyncTask<String, String, String>
{
protected ProgressDialog dialog;
public String wsURL;
public String wsFunction;
public String wsInput;
public int codeHTTP;
public String messageHTTP;
public String strResponse;
public WebServiceRestFull(Context act)
{
dialog = new ProgressDialog(act);
}
#Override
protected void onPreExecute() {
dialog.setMessage("Wait please...");
dialog.show();
}
#Override
protected void onPostExecute(String result)
{
if (dialog.isShowing())
{
dialog.dismiss();
}
}
#Override
protected String doInBackground(String... params)
{
String url = wsURL + wsFunction;
String inputCoded = EncodeString(wsInput);
HttpURLConnection request;
URL urlToRequest = new URL(url);
request = (HttpURLConnection) urlToRequest.openConnection();
request.setDoOutput(true);
request.setDoInput(true);
request.setRequestProperty("Content-Type", "application/json");
request.setRequestMethod("POST");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(request.getOutputStream());
outputStreamWriter.write("\""+inputCoded+"\"");
outputStreamWriter.flush();
outputStreamWriter.close();
codeHTTP = request.getResponseCode();
messageHTTP = request.getResponseMessage();
InputStream is = request.getInputStream();
String resp = convertStreamToString(is);
strResponse = DecodeString(resp);
request.disconnect();
return strResponse;
}
catch (Exception ex)
{
ex.printStackTrace();
return "ERROR";
}
}
}
On the other side, in the "Android Activity" I call this asynchronous class as follows:
WebServiceRestFull web = new WebServiceRestFull(this);
web.wsURL = "http://someurl.com/rest/etc";
web.wsFunction = "login";
web.wsInput = "mike";
web.execute();
Thread.sleep(1000);
The problem is that this is not actually do an asynchronous call and the results usually are not received by the webservice .
Is there any simple way to do this or am I doing wrong in some side as the call to webservice or own webservice class ?
Sorry for my english.
Thanks!

Nothing is wrong with the way you created and excecuted this asynctask
Just please don't use Thread.sleep();
And the issue is clearly in the doInBackground() method which code we don't have here

Is your code complete? There is nothing on your class that make an http request, the rest seems to be fine.
Try to use Okhttp it's really simple. Check it here
That thread sleep will run in main thread which is not such good idea.Use post execute to run you callback and publish any results.

Related

Async task HttpPost request DoInbackground call web api Android Studio Java, how to add body string array?

I am trying to send a raw body request Array, any idea how to implement the Body array string, in java android studio?
Web API .net framework c# working:
[Route("api/login_test")]
[HttpPost]
public object login_test([FromBody] string[] Username_Password])
{
string UsernameOrEmail_address, Password;
UsernameOrEmail_address = Username_Password[0];
Password = Username_Password[1];
return UsernameOrEmail_address + " " + Password;
}
Below what i am trying to achieve, this also as a reference,web api c# test on postman and working Java Async Task from android studio:
/**
* Async task class to get json by making HTTP call
*/
private class login_test extends AsyncTask<Void, Void, Void> {
HttpURLConnection conn = null ;
BufferedReader reader = null;
#Override
protected Void doInBackground(Void... voids) {
try {
URL url_login;
url_login = new URL(url_api + "login_test");
conn = (HttpURLConnection) url_login.openConnection();
conn.setRequestMethod("POST");
JSONArray jsonArray = new JSONArray();
jsonArray.put(0, username);
jsonArray.put(1, password);
OutputStreamWriter osw = new OutputStreamWriter(conn.getOutputStream());
osw.write(String.valueOf(jsonArray));
Log.i("Body to API", String.valueOf(jsonArray));
osw.flush();
osw.close();
}
}
}
I tried above, but it is not success because somehow it is not being written right, and i am getting exception as it fails
I found my issue, I had to a Content-Type as application/json
conn.setRequestProperty("Content-Type","application/json");

java.net.ProtocolException: method does not support a request body: GET

I'm trying to send POST request from the android studio and I get some errors like:
E/ERROR:: method does not support a request body: GET
java.net.ProtocolException: method does not support a request body: GET
And I don't know how to resolve it. Can anyone help me?
This is my main class where I'm sending port request
public class Main2Activity extends AppCompatActivity {
public TextView content;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
content = (TextView) findViewById(R.id.content);
new CheckConnectionStatus().execute("https://nonoperational-trad.000webhostapp.com/getuser.php");
}
class CheckConnectionStatus extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
content.setText("");
}
protected String doInBackground(String...params) {
URL url = null;
try {
url = new URL(params[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection urlConnection =(HttpURLConnection) url.openConnection();
urlConnection.setDoInput(true);
Uri.Builder builder = (Uri.Builder) new Uri.Builder()
.appendQueryParameter("username", "d")
.appendQueryParameter("password","d");
OutputStream outputStream= urlConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
bufferedWriter.write(builder.build().getEncodedQuery());
bufferedWriter.flush();
bufferedWriter.close();
outputStream.close();
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
bufferedReader.close();
return s;
} catch (IOException e) {
Log.e("ERROR:", e.getMessage(), e);
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String s){
super.onPostExecute(s);
content.setText(s);
}
}
}
build.gradle that I added - implementation 'com.squareup.okhttp3:okhttp:3.9.1'
This is the error message while sending the request!
E/ERROR:: method does not support a request body: GET
java.net.ProtocolException: method does not support a request body: GET
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:262)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:26)
at com.example.dato.maptest.Main2Activity$CheckConnectionStatus.doInBackground(Main2Activity.java:65)
at com.example.dato.maptest.Main2Activity$CheckConnectionStatus.doInBackground(Main2Activity.java:42)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
Looks like the API that you are trying to call is a GET request. Hence you need to make a GET request (not a POST request).
Even though you have mentioned that you are using OkHttp for the API call, I do not see any sign of using it. I see that you have used basic HttpUrlConnection for making the server request.
Usually, I use Volley for making API calls. You can find how to use Volley for making an API call from the link provided. Here's I am trying to write some code, however, you may have to modify the code as per your need.
First, you need to add the following dependency in your build.gradle file.
dependencies {
// ... Your other dependencies go here
implementation 'com.android.volley:volley:1.1.1'
}
Then you just have to write the following code where you want to call this API.
String username = "d";
String password = "d";
RequestQueue queue = Volley.newRequestQueue(this);
String url ="https://nonoperational-trad.000webhostapp.com/getuser.php?username=" + username + "&password=" + password;
// Request a String response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(Main2Activity.this, response, Toast.LENGTH_LONG).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(Main2Activity.this, "Fail", Toast.LENGTH_LONG).show();
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
I tried calling the API using Postman and got the following response.
Hope that helps!

php : reading json arraylist and saving data in mysql?

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

Retrofit Error :500 Internal server error in Android

Am Using retrofit for my connection with server,My app has signin page and signout page During Login i get the value from text box and send using POST request to the server It works fine,
public void LoginUser(View v)
{RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ROOT_URL)
.build();
WashAPI api = adapter.create(WashAPI.class);
api.LoginUser(
Email.getText().toString(),
Password.getText().toString(),
//Creating an anonymous callback
new Callback<Response>() {
#Override
public void success(Response result, Response response) {
//On success we will read the server's output using bufferedreader
//Creating a bufferedreader object
BufferedReader reader = null;
//An string to store output from the server
String output = "";
try {
//Initializing buffered reader
reader = new BufferedReader(new InputStreamReader(result.getBody().in()));
//Reading the output in the string
output = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
Interface for signin
public interface WashAPI {
#FormUrlEncoded
#POST("/xxx/yyy/signin")
public void LoginUser(
#Field("email") String email,
#Field("password") String password,
Callback<Response> callback);
}
This works good
After login with my server API it returns me a token, At the time of signout i need to send the token so my session get experied.
code for signout
public void signout(View v)
{
Log.d("insidetoken",t);
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ROOT_URL)
.build();
SignoutAPI api = adapter.create(SignoutAPI.class);
api.signout(t,
new Callback<Response>() {
#Override
public void success(Response result, Response response) {
BufferedReader reader = null;
String output = "";
try {
reader = new BufferedReader(new InputStreamReader(result.getBody().in()));
output = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
Interface for signout
public interface SignoutAPI {
#FormUrlEncoded
#POST("/xxx/yyy/zzz/signout")
public void signout(
#Field("token") String token,
Callback<Response> callback);
}
My code is same for both signin and sigout
but for signin it works and for signout it gives me RETROFIT ERROR : 500 INTERNAL SERVER ERROR
But Using POSTMAN It works fine
500 INTERNAL SERVER ERROR means that there is problem in the server side you should have to check it using postman.
I am damn sure that there will be problem in the web service response not of your code at android side.
As mentioned in the comments too, it appears you are doing something in the login service that is not being done in the sign out service.
To fix this, make sure in you sign out service, you are checking for a POST parameter named token.
Maybe you are giving token in wrong way
In my way It was "Bearer TOKEN" -> for Authorization in Header
In my case I changed my parameters to that
fun setProfileAvatar(token: String,#Part image: MultipartBody.Part) : Single<Message> {
return apiService.setProfileAvatar("Bearer ${token}",image)
}
You can enable logging in retrofit to show you server-side errors and messages.
use this link to understand how to enable it.
https://stackoverflow.com/a/33256827/9474700

JSON response is getting cut off, Android

I've seen multiple posts about this topic, but none of them seem to be the solution to my problem.
The problem is that the JSON response from the server is getting cut off and therefore I'm getting a JSONException when trying to get the response into a JSONArray.
json = new JSONArray(EntityUtils.toString(response.getEntity()));
Here is the whole code:
private class AsyncFetchForms extends AsyncTask<String, Void, JSONArray> {
private HttpClient mClient = new DefaultHttpClient();
private AsyncTaskCompleteListener<JSONArray> listener;
private String serverUrl;
private String credentials;
private ProgressDialog progressDialog;
private HttpGet httpGet;
private String response;
private BasicResponseHandler responseHandler;
private boolean showDialog;
private JSONArray json;
public AsyncFetchForms(String url, String message, AsyncTaskCompleteListener<JSONArray> listener, boolean showDialog)
{
serverUrl = Utils.getServerUrl(context) + url;
credentials = Utils.getUserCredentials(context);
this.listener = listener;
this.showDialog = showDialog;
httpGet = new HttpGet(serverUrl);
httpGet.setHeader("Authorization", "Basic " + credentials);
httpGet.setHeader("Accept", "application/json");
httpGet.setHeader("Accept-Encoding", "gzip");
httpGet.setHeader("Connection", "keep-alive");
responseHandler = new BasicResponseHandler();
if(showDialog)
{
progressDialog = new ProgressDialog(context);
progressDialog.setMessage(message);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
}
}
#Override
protected JSONArray doInBackground(String... params) {
try {
HttpResponse response = mClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
json = new JSONArray(EntityUtils.toString(response.getEntity()));
return json;
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(JSONArray result) {
System.out.println(result.toString());
}
}
Can anyone see the problem?
Logcat can only show about 4000 characters. So you will have to implement a recursive function to see the entire log. Use below function to see the entire log:
public static void longInfo(String str) {
if (str.length() > 4000) {
Log.d("", str.substring(0, 4000));
longInfo(str.substring(4000));
} else
Log.d("", str);
}
If you (or your team) implement the server side yourself, first thing I'd check is if the server is returning the correct HTTP response. In particular, if you transfer the data by HTTP, you need to have correct Content-Length or otherwise your data will be cut off. Also, Content-Length must be the length of data after any Transfer Encodings are applied, in other words, after the length of the data after being gzipped. Alternatively, use chunked transfer.
Second, make sure that your server is generating valid JSON. Maybe you missed a closing parentheses or so. Maybe you need to parse JSON Object rather JSON Array.
Also, if you receive exceptions, please always post the the entire traceback.
First of all, try to log the EntityUtils.toString(response.getEntity()) response and make sure that it starts with "[" not "{" ie. it's a jsonArray not jsonObject.
Then try to open the url in your browser ,if avilable, and make sure that there are no encoding issues.
Finally, if the problem is still exists please send us the error log output.
This answer is completely out of the subject but :
What are you trying do here ? Do you know that there are libraries which are doing all this boring job for you ?
When I talk about boring job, I'm talking about managing all the background running stuff (like AsyncTask), JSON decoding and HTTP response. I know that it's sometimes a pain in the a** (I've been there) but now I've choose to not worry anymore and use a dedicated library : http://square.github.io/retrofit/
This little baby will contact the Webservice of your choice, download the JSON and put it into a custom java class with all the attributes you want to deal with.
If you plug it with something like ORMLite, it can even save your JSON response object into a SQLite DB that you can access in the same way (it "populates" a java class object by setting all the attributes for you).
Personally I can't imagine myself doing all this stuff by hand anymore, it's just trouble without the benefits =)

Categories