I’m trying to load map tiles from an internal SSL server. The SSL certificate’s root of trust is not recognized by the Android system.
W/o*.o*.t*.m*.MapTileDow*(2837): IOException downloading MapTile: /8/37/4 :
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
I’m already familiar with the problem and have solved it in the rest of the application based on this excellent SO answer. Essentially, I extended my own SSLSocketFactory and X509TrustManager which load my SSL certificate’s root of trust from a .bks file bundled with the app. To create a secure connection, I call ((HttpsURLConnection) connection).setSSLSocketFactory(mySSLSocketFactory) and the certificate is verified using my classes with my root of trust.
My question is how do I do the same thing for osmdroid? I’m creating my own XYTileSource where I set the URL, file extension, size, etc. of my map tiles. I see that osmdroid creates its connections to download map tile images in MapTileDownloader. I can write my own replacement class that will address the SSL issue in the same manner, but how do I tell osmdroid to use my custom downloader instead of the default?
It turns out this is possible without changing the source of osmdroid, due to the
public MapView(Context context, int tileSizePixels, ResourceProxy resourceProxy, MapTileProviderBase aTileProvider)constrtuctor.Assuming you already have a custom class like
MySSLSocketFactory(whichextends javax.net.ssl.SSLSocketFactory), the basic process looks like this:Create a drop-in replacement class for
MapTileDownloaderto perform the download in a way that makes use ofMySSLSocketFactory. Let’s call thisMyTileDownloader.Create a drop-in replacement class for
MapTileProviderBasicthat instantiates your customMyTileDownloader. Let’s call thisMyTileProvider.Instantiate your tile source as a
new XYTileSource(no need to write a custom class).Instantiate
MyTileProviderwith your tile source instance.Instantiate
MapVewwith your tile provider instance.MySSLSocketFactoryis left as an exercise for the reader. See this post.MyTileDownloaderlooks something like this:MyTileProviderlooks something like this.Note that you’ll need a way to get access to your instance of
MySSLSocketFactoryinside this class. This is left as an exercise for the reader. I did this usingapp.getSSLSocketFactory(), whereappis an instance of a custom class thatextends Application, but your mileage may vary.Finally, the instantiation looks something like this: