React-native-code-push: [ANDROID 4 (KITKAT)] Push success but App no update.

Created on 20 Mar 2019  Â·  26Comments  Â·  Source: microsoft/react-native-code-push

Steps to Reproduce

  1. Code push success
  2. Open app nothing happened no update try to log using alert getting status UNKNOWN_ERROR

Expected Behavior

Code push should update the app after the user closes the App and restart manually. Then only the update will show up in the App.

Actual Behavior

What actually happens?
Nothing happened, no update. And when i use it on splash screen and using loading it will get stuck on loading

Reproducible Demo

Environment

  • I have try two env

  • react-native-code-push version: 5.3.2 and newest version

  • react-native version: 0.57.2 and newest version
  • iOS/Android/Windows version: Android Kitkat
  • Does this reproduce on a debug build or release build ? Release build
  • Does this reproduce on a simulator, or only on a physical device? Both

(The more info the faster we will be able to address it!)

android bug fix-in-master investigating

Most helpful comment

@Brioni, @Gerlison Sorry for the delay! I created a gist for the updated files [v5.6.0].
You can put them into your-project-path/node_modules/react-native-code-push/android/app/src/main/java/com/microsoft/codepush/react:

Please let me know if this helps or if you have any questions.

All 26 comments

Hey, have the same issue. I've attached android debugger so here is the specific error:

  • ReactNative 0.57.8
  • CodePush 5.5.2
  • Simulator/Physcial device
  • OS: Android 4.4.2

03-21 05:42:45.043 4907-4969/com.myapp.etc/ReactNative: [CodePush] Exception java.net.ConnectException: failed to connect to codepushupdates.azureedge.net/2a02:26f0:132::215:4a51 (port 443): connect failed: EHOSTUNREACH (No route to host) at libcore.io.IoBridge.connect(IoBridge.java:114) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459) at java.net.Socket.connect(Socket.java:843) at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131) at com.android.okhttp.Connection.connect(Connection.java:101) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294) at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206) at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)

### IT'S SUPER URGENT - CUZ MANDATORY UPDATES ARE NOT DELIVERED TO THOSE DEVICES

Hi @Rezaramdhanisti, @jpacyfik ,
Thanks for reporting!

Yeah, I've reproduced it. I'll investigate it as soon as possible. I'll be keep you posted.

@alexandergoncharov any update? It's critical because our app is based on CodePush updates - tens of clients are pinging us every hour. Any chance for getting ETA ?

Hey @jpacyfik,
Sorry for the delay!

We've tested this and found out that it's related to SSLv3 which is used in android <= 4.4 and as I understand https://codepushupdates.azureedge.net doesn't support it.

I found and tested a workaround (here):

I've added TLSSocketFactory class:

public class TLSSocketFactory extends SSLSocketFactory {

  private SSLSocketFactory delegate;

  public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, null, null);
    delegate = context.getSocketFactory();
  }

  @Override
  public String[] getDefaultCipherSuites() {
    return delegate.getDefaultCipherSuites();
  }

  @Override
  public String[] getSupportedCipherSuites() {
    return delegate.getSupportedCipherSuites();
  }

  @Override
  public Socket createSocket() throws IOException {
    return enableTLSOnSocket(delegate.createSocket());
  }

  @Override
  public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
    return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
  }

  @Override
  public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
    return enableTLSOnSocket(delegate.createSocket(host, port));
  }

  @Override
  public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
      throws IOException, UnknownHostException {
    return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
  }

  @Override
  public Socket createSocket(InetAddress host, int port) throws IOException {
    return enableTLSOnSocket(delegate.createSocket(host, port));
  }

  @Override
  public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
      throws IOException {
    return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
  }

  private Socket enableTLSOnSocket(Socket socket) {
    if (socket != null && (socket instanceof SSLSocket)) {
      ((SSLSocket) socket).setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
    }
    return socket;
  }
}

and edited CodePushUpdateManager.java (line 161+):

HttpsURLConnection connection = null;
...

try {
    URL downloadUrl = new URL(downloadUrlString);

    connection = (HttpsURLConnection) downloadUrl.openConnection();

    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        if (downloadUrl.toString().startsWith("https")) {
            try {
                connection.setSSLSocketFactory(new TLSSocketFactory());
            } catch (Exception e) {
                CodePushUtils.log(e.getMessage());
            }
        }
    }
    ...

And it works.

We need some time to fix this issue properly, but for now you can try to use this workaround as a temporary solution.

@yuri-kulikov thanks for the workaround! I'll try it out and let You know :)

Hi the setSSLSocketFactory is red for some reason in the code below?

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
if (downloadUrl.toString().startsWith("https")) {
try {
connection.setSSLSocketFactory(new TLSSocketFactory());
} catch (Exception e) {
CodePushUtils.log(e.getMessage());
}
}
}

Hi the setSSLSocketFactory is red for some reason in the code below?

@afrakhan123 I suppose you need to replace HttpURLConnection with HttpsURLConnection (connection type).

@yuri-kulikov Everything works as expected - I've deployed hot-fix version yesterday. Thanks for help :) However, any plans for including that (or more proper fix) in next release?

Screen Shot 2019-03-25 at 21 06 35

still not working with HttpsURLConnection

However, any plans for including that (or more proper fix) in next release?

@jpacyfik I hope we'll fix it in the next release, but we need to do more research on how to fix this correctly.

still not working with HttpsURLConnection

@afrakhan123, I think this could be the reason:

HttpsURLConnection connection = null; // <- Be sure to change this as well
...

// Download the file while checking if it is a zip and notifying client of progress.
try {
    URL downloadUrl = new URL(downloadUrlString);

    connection = (HttpsURLConnection) downloadUrl.openConnection();
    ...

thanks a lot!! that worked and sorry for being thick :)

@yuri-kulikov not work for me:
"react-native": "0.58.4",
react-native-code-push": "^5.5.2",
edited CodePushUpdateManager.java
and react-native run-android command got 4 errors
error: cannot find symbol: HttpsURLConnection connection = null;
error: cannot find symbol: connection = (HttpsURLConnection) downloadUrl.openConnection();
error: package Build does not exist if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
error: cannot find symbol connection.setSSLSocketFactory(new TLSSocketFactory());
Can you tell me what I'm doing wrong?

Hi @Brioni I suppose you need to add the necessary imports for all this.

@yuri-kulikov Thanks for response, but can you put here All files / lines what we need to change inside nodu_modules/react-native-code-push? If it is important - for "react-native-code-push": "^5.6.0", version.


Quote

Hey @jpacyfik,
Sorry for the delay!

We've tested this and found out that it's related to SSLv3 which is used in android <= 4.4 and as I understand https://codepushupdates.azureedge.net doesn't support it.

I found and tested a workaround (here):

I've added TLSSocketFactory class:

public class TLSSocketFactory extends SSLSocketFactory {

  private SSLSocketFactory delegate;

  public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, null, null);
    delegate = context.getSocketFactory();
  }

  @Override
  public String[] getDefaultCipherSuites() {
    return delegate.getDefaultCipherSuites();
  }

  @Override
  public String[] getSupportedCipherSuites() {
    return delegate.getSupportedCipherSuites();
  }

  @Override
  public Socket createSocket() throws IOException {
    return enableTLSOnSocket(delegate.createSocket());
  }

  @Override
  public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
    return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
  }

  @Override
  public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
    return enableTLSOnSocket(delegate.createSocket(host, port));
  }

  @Override
  public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
      throws IOException, UnknownHostException {
    return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
  }

  @Override
  public Socket createSocket(InetAddress host, int port) throws IOException {
    return enableTLSOnSocket(delegate.createSocket(host, port));
  }

  @Override
  public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
      throws IOException {
    return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
  }

  private Socket enableTLSOnSocket(Socket socket) {
    if (socket != null && (socket instanceof SSLSocket)) {
      ((SSLSocket) socket).setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
    }
    return socket;
  }
}

and edited CodePushUpdateManager.java (line 161+):

HttpsURLConnection connection = null;
...

try {
    URL downloadUrl = new URL(downloadUrlString);

    connection = (HttpsURLConnection) downloadUrl.openConnection();

    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        if (downloadUrl.toString().startsWith("https")) {
            try {
                connection.setSSLSocketFactory(new TLSSocketFactory());
            } catch (Exception e) {
                CodePushUtils.log(e.getMessage());
            }
        }
    }
    ...

And it works.

We need some time to fix this issue properly, but for now you can try to use this workaround as a temporary solution.

How to do this in the code-push ^5.6.0, i can't find the files you refered, :(

@Brioni, @Gerlison Sorry for the delay! I created a gist for the updated files [v5.6.0].
You can put them into your-project-path/node_modules/react-native-code-push/android/app/src/main/java/com/microsoft/codepush/react:

Please let me know if this helps or if you have any questions.

@yuri-kulikov For release build of the app, Do we need to write a post installation script in package.json to include these above 2 files you mentioned ?

@Udbhav12 I think it's a possible solution. Unfortunately, this is only a workaround, we are still looking for a good solution that will allow us to solve this problem (perhaps even without changing the code, on the Azure side).

@yuri-kulikov That would be great. I'm facing the same issue on cordova (check here)

Solving the problem on Azure side would solve for all plugins.

@Brioni, @Gerlison Sorry for the delay! I created a gist for the updated files [v5.6.0].
You can put them into your-project-path/node_modules/react-native-code-push/android/app/src/main/java/com/microsoft/codepush/react:

Please let me know if this helps or if you have any questions.

Thank you very much. It worked, sorry for the delay. I've tested with emulators on the debug release on android 4.4.2, i'll still test in production, but it seems like to work perfectly.

@Brioni, @Gerlison Sorry for the delay! I created a gist for the updated files [v5.6.0].
You can put them into your-project-path/node_modules/react-native-code-push/android/app/src/main/java/com/microsoft/codepush/react:

Please let me know if this helps or if you have any questions.

@yuri-kulikov These files are in node_modules which means they will be overridden on running npm install, right? or am I missing something?

I can always fork the react-native-code-push package, change the files and then use that fork in my project as npm dependency. Just wanted to confirm that I'm not missing something obvious here.

Also, is there an update on the proper fix for this?

Thanks!

I'am facing the same issue @yuri-kulikov solution work on me (thanks for that) but Is there have any improvement azure side or code push

Hey Guys,

Just wondering if you have any updates on this one. I currently uses the version with the work around proposed by @yuri-kulikov however I'm upgrading the version of RN and the codepush version. I didn't found something similar as a final solution into the latest version. Just wondering if we should keep using the workaround or have a fix in place and I didn't see it.

Thanks in advance.

Any updates? Will @yuri-kulikov‘s code be merged in ?

Hey all, sorry for the delay.

We have released a fix for this issue and now #1957 in master. As far as we know, react-native currently has a number of problems with devices running on android 4.x and low. We recommend you use android 5.x and higher versions for stable work of react-native-code-push.

@yuri-kulikov
What if code push returns network request failed?
Works fine on other devices.
The rest of the fetch requests work.
Did everything that was written above
Android 4.4

Was this page helpful?
0 / 5 - 0 ratings