How can I make Android Volley perform HTTPS request, using a certificate self-signed by an Unknown CA?
<p>Before making the question, I found some links, which I checked, one by one, and none of them, gives me a solution:</p>

<ul>
<li><strong>well-kown CA</strong>
<a href="https://stackoverflow.com/questions/21555404/https-request-using-volley">HTTPS request using volley</a></li>
<li><strong>accept all SSL certificates</strong>
<a href="https://stackoverflow.com/questions/26412417/no-peer-certificate-exception-volley-and-android-with-self-signed-certificate">No peer certificate Exception - Volley and Android with self signed certificate</a></li>
<li><strong>Node.js (Socket.io)</strong>
<a href="https://stackoverflow.com/questions/15365772/socket-io-ssl-self-signed-ca-certificate-gives-error-when-connecting">Socket.io + SSL + self-signed CA certificate gives error when connecting</a></li>
<li><strong>Self-Signed Certificate "MANUALLY" imported:</strong>
<a href="https://stackoverflow.com/questions/19433058/android-ssl-http-request-using-self-signed-cert-and-ca">Android SSL HTTP Request using self signed cert and CA</a></li>
</ul>

<p>The only link which I have found until now, is this one, which gives two approaches: <a href="https://stackoverflow.com/questions/17045795/making-a-https-request-using-android-volley">Making a HTTPS request using Android Volley</a></p>

<ul>
<li>1º Instructs to import some classes to your app, when indeed, there are another classes that must be imported, and the classes are using deprecated libs from "apache.org"</li>
<li>2º A example to NUKE all SSL ceriticates (pretty bad idea...)</li>
</ul>

<p><br>
I also have found this blog, which has a plenty of explanations, but at the end, I realized that the examples are using deprecated libraries from "apache.org" and also, the blog itself doesn't have a content for Android Volley.
<a href="https://nelenkov.blogspot.mx/2011/12/using-custom-certificate-trust-store-on.html" rel="nofollow noreferrer">https://nelenkov.blogspot.mx/2011/12/using-custom-certificate-trust-store-on.html</a></p>

<p><br>
There is also this link from Android and the code of "Unknown certificate authority" section, which gives a good idea about the solution, but the code itself, lacks something in its structure (Android Studio complaining...): <a href="https://developer.android.com/training/articles/security-ssl.html" rel="nofollow noreferrer">https://developer.android.com/training/articles/security-ssl.html</a></p>

<p>But this quote from the link, seems the core concept for solving the problem.</p>

<p><strong><em>"A TrustManager is what the system uses to validate certificates from the server and—by creating one from a KeyStore with one or more CAs—those will be the only CAs trusted by that TrustManager.
Given the new TrustManager, the example initializes a new SSLContext which provides an SSLSocketFactory you can use to override the default SSLSocketFactory from HttpsURLConnection. This way the connection will use your CAs for certificate validation."</em></strong></p>

<p><br><br>
<strong>And now, here is my problem:</strong> I have a webserver that is using a self-signed certificate and I have created a "BKS truststore" based on its certificate. I have imported de BKS truststore to my Android APP and now, I have the following code on my App (I'm just posting here the MainActivity, which is the only class that has relevance to this subject until now, I suppose):</p>

<pre><code>package com.domain.myapp;


import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import android.widget.EditText;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HurlStack;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import java.io.InputStream;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;


public class LoginScreen extends AppCompatActivity {

Context ctx          = null;
InputStream inStream = null;
HurlStack hurlStack  = null;

EditText username    = null;
EditText password    = null;
String loginStatus   = null;

public LoginScreen() {

    try {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        KeyStore ks = KeyStore.getInstance("BKS");
        inStream = ctx.getApplicationContext().getResources().openRawResource(R.raw.mytruststore);
        ks.load(inStream, null);
        inStream.close();
        tmf.init(ks);
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
        final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        hurlStack = new HurlStack(null, sslSocketFactory);
    } catch (Exception e){
        Log.d("Exception:",e.toString());
    }
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login_screen);
    username = (EditText) findViewById(R.id.user);
    password = (EditText) findViewById(R.id.passwd);
}

public void login(View view) {

    RequestQueue queue = Volley.newRequestQueue(this, hurlStack);
    final String url = "https://myserver.domain.com/app/login";

    StringRequest postRequest = new StringRequest(Request.Method.POST, url,
            new Response.Listener&lt;String&gt;()
            {
                @Override
                public void onResponse(String response) {
                    Log.d("Response", response);
                    loginStatus = "OK";
                }
            },
            new Response.ErrorListener()
            {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.d("Error.Response", String.valueOf(error));
                    loginStatus = "NOK";
                }
            }
    ) {
        @Override
        protected Map&lt;String, String&gt; getParams()
        {
            Map&lt;String, String&gt;  params = new HashMap&lt;String, String&gt;();
            params.put("username", String.valueOf(user));
            params.put("domain", String.valueOf(passwd));

            return params;
        }
    };
    queue.add(postRequest);

    if (loginStatus == "OK") {
        Intent intent = new Intent(LoginScreen.this, OptionScreen.class);
        startActivity(intent);
    } else {
        Toast.makeText(getApplicationContext(), "Login failed",Toast.LENGTH_SHORT).show();
    }
}

}
</code></pre>

<p>Regarding the constructor class, I took the liberty of copying the code, putting some comments about what do I understand from each part of it:</p>

<pre><code>try {
// I have a TrustManagerFactory object
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// I have a KeyStore considering BKS (BOUNCY CASTLE) KeyStore object
KeyStore ks = KeyStore.getInstance("BKS");
// I have configured a inputStream using my TrustStore file as a Raw Resource
inStream = ctx.getApplicationContext().getResources().openRawResource(R.raw.mytruststore);
// I have loaded my Raw Resource into the KeyStore object
ks.load(inStream, null);
inStream.close();
// I have initialiazed my Trust Manager Factory, using my Key Store Object
tmf.init(ks);
// I have created a new SSL Context object
SSLContext sslContext = SSLContext.getInstance("TLS");
// I have initialized my new SSL Context, with the configured Trust Managers found on my Trust Store
sslContext.init(null, tmf.getTrustManagers(), null);
// I have configured a HttpClientStack, using my brand new Socket Context
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
hurlStack = new HurlStack(null, sslSocketFactory);
} catch (Exception e){
Log.d("Exception:",e.toString());
}
</code></pre>

<p>After this, in another Class Method, I have the RequestQueue, using the HttpClientStack which I have configured on the Class COnstructor:</p>

<pre><code>RequestQueue queue = Volley.newRequestQueue(this, hurlStack);
final String url = "https://myserver.domain.com/app/login";
StringRequest postRequest = new StringRequest(Request.Method.POST, url,new Response.Listener&lt;String&gt;()
    {
    ...
    ...
    }
</code></pre>

<p>When I run my app, giving the user and password which is expected by my WebServer, I can see in the Android Monitor from Android Studio the following messages:</p>

<blockquote>
  <p>09-17 21:57:13.842 20617-20617/com.domain.myapp D/Error.Response:
  com.android.volley.NoConnectionError:
  javax.net.ssl.SSLHandshakeException:
  java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. </p>
</blockquote>

<p>After all this explanation, I have the following question:</p>

<ul>
<li><strong>What else must be configured in order to make Android accept the SSL certificate from the CA of the custom TrustManager which I have configured at the constructor of the class?</strong></li>
</ul>

<p>Forgive me, but I'm beginner on Android programming, as well on Java, so maybe, I'm making a terrible mistake...</p>

<p>Any help, would be much appreciated. </p>

<p><strong>UPDATE</strong></p>

<p>I have improved the constructor of the class, doing a better grouping of the statements, and also using the <strong>KeyManagerFactory</strong>, which seems to be pretty important on this process. Here goes:</p>

<pre><code>public class LoginScreen extends AppCompatActivity {

...
...

  public LoginScreen() {

    try {
        inStream = this.getApplicationContext().getResources().openRawResource(R.raw.mytruststore);

        KeyStore ks = KeyStore.getInstance("BKS");
        ks.load(inStream, "bks*password".toCharArray());
        inStream.close();

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
        kmf.init(ks, "bks*password".toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
        tmf.init(ks);

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(),tmf.getTrustManagers(), null);
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        hurlStack = new HurlStack(null, sslSocketFactory);
    } catch (Exception e){
        Log.d("Exception:",e.toString());
    }

  }

...
...

}
</code></pre>

<p>Anyway, I'm still having problems..</p>

<blockquote>
  <p>Response: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.</p>
</blockquote>