NativeScript: HTTPS request on Android 4.4 (API-19) javax.net.ssl.SSLException: Connection closed by peer

HTTP request made on Android 4.4 throws with

System.err: javax.net.ssl.SSLException: Connection closed by peer
System.err:     at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
System.err:     at com.android.okhttp.Connection.upgradeToTls(Connection.java:146)
System.err:     at com.android.okhttp.Connection.connect(Connection.java:107)
System.err:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
System.err:     at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
System.err:     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
System.err:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
System.err:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89)
System.err:     at com.android.okhttp.internal.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:161)
System.err:     at org.nativescript.widgets.Async$Http$HttpRequestTask.doInBackground(Async.java:543)
System.err:     at org.nativescript.widgets.Async$Http$1.run(Async.java:482)
System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
System.err:     at org.nativescript.widgets.Async$PriorityThreadFactory$1.run(Async.java:52)
System.err:     at java.lang.Thread.run(Thread.java:841)
JS: ERROR Error: Uncaught (in promise): Response with status: 200  for URL: null

The same works as expected on higher API levels (tested on API21, API 23 , API25).

Possible solution discussed here

<bountysource-plugin>

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource. </bountysource-plugin>

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 1
  • Comments: 22 (9 by maintainers)

Most upvoted comments

Reproducible with any HTTPS request only on Android API 19 devices with an older version of the gms security provider. As an easy workaround, we can force the device to update the security provider the following way:

app.ts

import { ad } from "tns-core-modules/utils/utils";
const context = ad.getApplicationContext();

androidApp.on(AndroidApplication.activityCreatedEvent, function (args: AndroidActivityBundleEventData) {

    // Needed updated Provider for corner cases with HTTP request using TSL on Android API19
    com.google.android.gms.security.ProviderInstaller.installIfNeededAsync(context, new com.google.android.gms.security.ProviderInstaller.ProviderInstallListener({
        onProviderInstalled:  () => {
            console.log("onProviderInstalled");
        },
        onProviderInstallFailed: (errorCode, intent) => {
            console.log("onProviderInstalledFailed");
            console.log("errorCode: " + errorCode);
        }
    }))
});

@NickIliev : thank you very much! Your solution works. Great!

@NickIliev ah kudos on that plugin declarations. At least my editor doesn’t give me the error, but …

// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
import { AppModule } from "./app/app.module";


import {
    android as androidApp,
    AndroidApplication,
    AndroidActivityBundleEventData,
} from "tns-core-modules/application";

import { ad } from "tns-core-modules/utils/utils";
declare let com: any;

if (androidApp) {
const context = ad.getApplicationContext();

androidApp.on(AndroidApplication.activityCreatedEvent, (
    args: AndroidActivityBundleEventData
) => {
    const builder = new android.os.StrictMode.VmPolicy.Builder();
    android.os.StrictMode.setVmPolicy(builder.build());

    // Needed for corner cases with HTTP request using TSL on Android API19
    com.google.android.gms.security.ProviderInstaller.installIfNeededAsync(
    context,
    new com.google.android.gms.security.ProviderInstaller.ProviderInstallListener(
        {
        onProviderInstalled: () => {
            console.log("Provider Installed!");
        },
        onProviderInstallFailed: (errorCode, intent) => {
            console.log("Error: " + errorCode);
        }
        }
    )
    );
});
}

platformNativeScriptDynamic().bootstrapModule(AppModule);

And ofcourse the reference.d.ts file.

Still gives me an error on runtime (and even dies) when I do

tns run android --bundle

I get something like

System.err: Calling js method onCreate failed
System.err: TypeError: Cannot read property 'android' of undefined
System.err: File: "file:///data/data/nl.coreelements.weethetsnel/files/app/vendor.js, line: 106571, column: 18

and it only happens when I use the

    com.google.android.gms.security.ProviderInstaller.installIfNeededAsync(
    context,
    new com.google.android.gms.security.ProviderInstaller.ProviderInstallListener(
        {
        onProviderInstalled: () => {
            console.log("Provider Installed!");
        },
        onProviderInstallFailed: (errorCode, intent) => {
            console.log("Error: " + errorCode);
        }
        }
    )
    );

block … help?

@fransyozef when you need to access the native APIs (Android or iOS) via TypeScript you will need a typings for the used namespaces, classes, properties, etc.

You can either cast to any (not recommended) or use tns-platform-declarations (recommended) which will not only resolve the TypeScript compilation errors but also provide IntelliSense for the converted APIs.

To enable the declarations do the following:

  • Install the plugin as devDependency (–save-dev)
npm i tns-platform-declarations --save-dev
  • Create a reference.d.ts file in the root project folder and place the following
/// <reference path="./node_modules/tns-platform-declarations/ios.d.ts" />
/// <reference path="./node_modules/tns-platform-declarations/android.d.ts" />

e.g. like done here

Now you will have the declaration files with all the typings and will also have intelliSense for the android namespace. More details in the documentation section or here

Note: the plugin won’t resolve the com namespace for which I am using manual casting to any

declare let com: any;