“Could not load SSL library” Error message on Android 6 Marshmallow with TidHTTP
I have recently upgraded from Android 4.4 KitKat to Android 6 Marshmallow and to my surprise I found out that the some of my applications stopped working. The main issue is related to HTTPS communications using Indy components. As you might know Indy does not implement SSL natively. What the component does is to implement a flexible IOHandler architecture that allows for any SSL implementation to be plugged into Indy. Indy itself implements its own IOHandler class that is based on OpenSSL.
The problem is that for Android 6, Google decided not to support OpenSSL anymore. Google replaced OpenSLL with a custom fork called BoringSSL to meet it's needs. BoringSSL includes additional changes and patches to the OpenSSL API and it's not backwards-compatible with OpenSSL. Android 6.0 will use the pre-loaded BoringSSL binaries when any application tries to load the OpenSSL library and it will throw an error (the reason why is because BoringSSL and OpenSSL share the same file names).
If you try to debug your Android application, you will see the following message when trying to use the TIdSSLIOHandlerSocketOpenSSL handler:
How to fix this error?
I found few comments in different forums and in the end the solution was not clear at all and I had to spend few hours fixing the issue myself. The best way to solve this is by deploying a recompiled version of the OpenSSL libraries with your Android application and then tell Indy to use those files. Indy operates at the NDK level so to make Indy avoid BoringSSL you will have to do that.
Get a precompiled version of OpenSSL here:
Place these files in your project and reference them in the deployment section. Go to Project -> Deployment and add the two files that are inside of that zip file and specify the destination folder in your Android device as .\assets\internal.
Now the last thing to do is to tell Indy where to look for these files. To do this, you will have to call the IdOpenSSLSetLibPath method with the TPath.GetDocumentsPath during startup (FormCreate for example). Here is an example:
Once completed, your applications should be able to use the correct version of Indy. You can review my solution and test it here:
If you need more help you can check the following threads:
I am from Brazil and I was having an email problem in my University project. Thank you so much!
ReplyDeleteGlad that it helped you!
DeleteCheers,
Jordi
I followed the steps in your guide and i get the following error message when I compile " Undeclared identifier: 'GetDocumentsPath'" I already declared the system.ioutils and IdSSLOpenSSLHeaders on the uses clauses, I am using delphi xe8, thanks in advance.
ReplyDeleteJordi, I already delete the line saved the file and add it again and the error disappear, but, when the line "Smtp.Connect;" is executed the Error message“Could not load SSL library” appears again, apparently the wrong version of the openssl libraries, how can I check the correct version, thanks in advance.
ReplyDeleteSorry, I was not putting the folder inside of the folder's proyect, thanks anyway.
Delete