How to solve javax.net.ssl.SSLHandshakeException: Connection closed by peer - java

Am trying to send http request using volley but am receiving error
javax.net.ssl.SSLHandshakeException: Connection closed by peer
I google around and try some suggestions but none solve my problem. please help
Bellow is the code am using
public class volley {
static RequestQueue queue=null;
public static String TAG = "MY_VOLLEY";
volley(final String URL,
final String Text
final Context context
){
helper.log(TAG,"Started Loading");
// Instantiate the RequestQueue.
if(queue==null) {
queue = Volley.newRequestQueue(context);
}
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(
Request.Method.POST, URL, new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
return;
}
}
){
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
try {
params.put("message",Text);
params.put("from",From);
} catch (Exception e) {
helper.log(TAG, "Error, hash map failed");
}
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
// Add the request to the RequestQueue.
queue.add(stringRequest);
return;
}
}

In terms of debugging the JSSE is a pain in the ...
Most likely the handshake fails and JSSE most of the time only shows you the final problem, i.e. that the server is closing the connection. Quite often the server is telling you the problem in an TLS alert message but that doesn't show up in the exception message.
If you have Wireshark or something similar installed, the easiest way is to fire up a session and look at the TLS-records (Wireshark shows them quite nicely so it's easy to recognize the error-packet containing the error-code and meaning).
If you don't have that tool, yet, you can activate SSL-debugging and look at the messages on STDOUT. Be warned that they are a bit hard to read if you're unfamiliar with TLS and - since it's a global setting - you should make sure that your tests happens when no other TLS-connection is established, otherwise you get mixed outputs. To enable TLS-handshake debugging, set the system property -Djavax.net.debug=ssl:handshake

Related

Problem in using a custom header to all my Volley requests

I want to make an Auth header for ALL my Volley requests
I have learnt how can I create a header overriding the getHeaders of the request class but I can not change it from every request from time to time and want to make it sort of static or global where I can change it and it changes everywhere. Here is what I have tried so far.
Main activity class
public class MainActivity extends AppCompatActivity {
RequestQueue requestQueue;
JsonObjectRequest jsonreq;
JSONObject object;
try{
requestQueue = Volley.newRequestQueue(MainActivity.this);
object=new JSONObject();
jsonreq=new JsonObjectRequest(Request.Method.POST, url, object, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
res=response.toString();
Log.d("log1","res : " + res);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("log1","Error from response : " +error.networkResponse.statusCode);
}
}) {
//want to get rid of this function from here and create in a global scope so I can control its implementation everywhere
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params=new HashMap<String,String>();
params.put("Authorization","xxxxxxxx");
return params;
}
};
requestQueue.add(jsonreq);
}
catch (Exception e){
Log.d("log1","error from catch " + e);
return e.toString();
}
return res;
I tried making a custom class that extends HurlStack and override the execute request. Here is the code for custom HurlStack class called GlobalHeaders
public class GlobalHeaders extends HurlStack {
String testing="xxxxxxxx";
#Override
public HttpResponse executeRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError {
Map<String, String> headers = request.getHeaders();
headers.put("Content-Type", "application/json; charset=utf-8");
headers.put("Authorization",testing);
return super.executeRequest(request, headers);
}
Now I am not sure how can I make use of this method in my main class where I am adding the requestQueue(jsonReq);
I tried other way were I override Request class of Volley with my custom class but again failed.
Please point how can I make this work or any other approach. I am a new learner to Java and Android.
Ok I have tried and this solution seems to work out. Posting here so It may also help someone in future.
Removed the getHeader method from the Main activity as the execute request gets called itself when I added its instance into the request using the below code.
if(stack == null){
stack=new GlobalHeaders();
requestQueue=Volley.newRequestQueue(getApplicationContext(),stack);
requestQueue.add(jsonreq);
}
Also need to change the first line in executeRequest method to cater the null exception to following
Map<String, String> headers = new HashMap<>(additionalHeaders);
and keep the return statement unchanged.

Android: Volley request is not working in released APK while works in debug

I have created a simple volley request for POST
//post request handler
public void PostRequest(final int queryType, String url, final String jsonData) {
StringRequest req = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
for (ApiRequestHandler commHandler : responseListeners) {
commHandler.responseHandler(response);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
for (ApiRequestHandler commHandler : errorListeners) {
commHandler.errorHandler(error);
}
}
}) {
#Override
public byte[] getBody() {
return jsonData.getBytes();
}
#Override
public String getBodyContentType() {
return "application/json";
}
#Override
public Map<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
};
getVolleyQueue().add(req);
}
This method works when I send request in debug mode (Android device connected to Android Studio), while it does not work when I release the app and I get a 400 error.
I have added Internet permissions.
It is difficult to debug when app is released, I just tried to toast when the error is received. The stacktrace is like that, but of no help to me.
com.android.volley.toolbox.BasicNetwork.a(Unknown Source:255),
com.android.volley.NetworkDispatcher.b(Unknown Source:37),
com.android.volley.NetworkDispatcher.run(Unknown Source:5)
I have spent like a day solving this, few of my pointers:
I could see body being blank when request sent from release on server side, but prints data at APK level
I also tried jsonData.getBytes("utf-8"); but didn't work
I am using implementation 'com.android.volley:volley:1.1.1'
I also need some guidelines on better ways to debug released apks. Thank you!
After little more digging, I could find the root cause:
The issue was because I have ProGuard enabled for release build type as minifyEnabled true. It compresses and obfuscates the code by various means like changing class names, variables, constants, etc.
Gson, uses dynamic key naming to make keys short.
To solve this, I used #SerializedName("keyName") annotation to let Gson know what to consider as the key.
For ex:
public class UserInfo {
#SerializedName("user_name")
public String userName;
#SerializedName("mobile")
public String mobile;
}
Hope this saves someone's day!

Android Volley unable to get data in response

I am trying to make a web-service call using volley and printing the response in the logcat. But I don't know why I am not getting response. Not even any error message.
Below is my code. I know I am missing something. Please correct me.
private void syncData() {
mProgressDialog.showProgressDialog("Initializing Please Wait...");
RequestQueue requestQueue = Volley.newRequestQueue(SalesDashboard.this);
StringRequest stringRequest = new StringRequest(Request.Method.POST, SYNC_DATA_SALES, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
mProgressDialog.dismissProgressDialog();
Log.e("TAG", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mProgressDialog.dismissProgressDialog();
Log.e("TAG", error.toString());
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String , String> params = new HashMap<>();
String userrole = mSessionManagement.getLoggedInUser().get(SESSION_USER_ROLE);
params.put("branch", mSessionManagement.getSelectedBranch());
params.put("staff_id", mSessionManagement.getLoggedInUser().get(SESSION_EMP_ID));
params.put("user_role", mSessionManagement.getLoggedInUser().get(SESSION_USER_ROLE));
params.put("user_dept", mSessionManagement.getLoggedInUser().get(SESSION_DEPT_IDS));
params.put("principal", mSessionManagement.getLoggedInUser().get(SESSION_PRINC_IDS));
if (userrole.equals(ADMIN) || userrole.equals(COUNTRY_MANAGER)) {
params.put("user_div", mSessionManagement.getSelectedDivision());
} else {
params.put("user_div", mSessionManagement.getLoggedInUser().get(SESSION_DIV_IDS));
}
return super.getParams();
}
};
requestQueue.add(stringRequest);
}
I am not receiving any error message also or any kind of exception. I have checked the webservice by hitting it on browser the response is displayed correctly on the browser but not able to fetch it in android.
Why you call super.getParams() on return instead params? Maybe it turn wrong on your request. Then try as follow
#Override
protected Map<String, String> getParams() throws AuthFailureError {
...
return params;
}
Bonus: use getMessage instead do toString() your error object
Print the stringRequest and check the url and cross verify with ur url
Before that check have u added Internet permissions in manifest file.

WearOS cannot make Volley request to an endpoint running on my computer's localhost

Problem
I'm attempting to make a simple POST JsonObjectRequest from a Huawei Watch and I keep getting com.android.volley.TimeoutError. I can successfully make other POST JsonObjectRequests from the watch to a different endpoint (not on my computer's localhost) and I can successfully make requests to the desired endpoint from a laptop.
What I've Tried:
Most posts suggest that this error is due to a bad connection or an incorrect endpoint. I tried increasing the timeout period to see if my connection was just slow but this did not fix things. The endpoint is definitely correct as it works when I make the request from a laptop.
I read on several posts that there are issues when connecting to unknown certificates. I followed the quick fix outline here: https://newfivefour.com/android-trust-all-ssl-certificates.html but this made no difference
My Code
mRequestQueue.add(volleyRequest());
...
private JsonObjectRequest volleyRequest(){
JSONObject data = null;
try{
data = new JSONObject("{'some':'data','other':'data'}");
} catch (JSONException e){
e.printStackTrace();
}
JsonObjectRequest request = new JsonObjectRequest(POST, mPath, data,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i("Volley Response", response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("Volley Error", error.toString());
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("Authorization", mToken);
return headers;
}
};
return request;
}

Volley Post Method MultiParams Error

I was trying Post method with using Volley and I got: com.android.google.volley server error.
I tested my api in postman and it works.
Here is my code:
StringRequest request=new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("Response", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error :",error.getMessage());
}
}) {
#Override
public Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("name", film.toString());
params.put("email", spin.toString());
params.put("password", spin_iki.toString());
params.put("address", spin_uc.toString());
params.put("brand", name.toString());
return params;
}
};
RequestQueue queue= Volley.newRequestQueue(film.this);
queue.add(request);
}
});
Normally I use my api like http://myurl/api/values/Post?film=...&email=...
How can I fix this? Thank you.This my API's Post method code
[HttpPost]
public int Post_film(string name, string email, string password, string address, string brand)
{
using (var context = new Entities())
{
db_table nesne = new db_table();
nesne.name =name;
nesne.email = email;
nesne.password = password;
nesne.address = address;
nesne.brand = brand;
context.db_table.Add(nesne);
int i = context.SaveChanges();
return i;
}
}
this my Postman SS
enter image description here
OK, you're sending a POST request but still adding parameters via URL. If your server is taking these parameters from the URL, then your Volley request will never work because overriding getParams() only works for parameters inside the request body, not parameters attached to the URL. You should either change the way your server is taking the parameters or, in your Android code, generate a string URL with all the parameters attached to it like "http:://myUrl.com/?email=something&name=something". To me, the most logical option is to change your server side code, because it doesn't make too much sense to expect a POST request with parameters in the URL. Parameters in POST requests should be inside the request body,

Categories

Resources