NSURLSession code not working in Xcode7 but the same code works in xcode6 - nsurlsession

I am having some issue with using NSURLSession in Xcode7 and Swift2. For some reason I keep getting NSURLErrordomain error but the same code
is working on Xcode6 with swift 1.2.
let baseURL = NSURL(string: "https://itunes.apple.com/search?term=one%20republic")
let downloadTask = session.downloadTaskWithURL(baseURL!, completionHandler: { (location, response, error) -> Void in
if(error == nil){
let objectData = NSData(contentsOfURL: location!)
let tmpData :NSString = NSString(data: objectData!, encoding: NSUTF8StringEncoding)!
print("success")
} else {
print("Failed")
}
})
downloadTask!.resume()
It keeps giving me NSURLDomain Error Please let me know if I am missing something here.

Transport Application Security is described here:
https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/
You should add the proper exception on a server by server basis, NSAllowsArbitraryLoads just disables AppTransportSecurity completely;
This is discouraged, and eventually could get your app rejected.
You should use NSExceptions only when you can't use proper https on all urls, e.g. when the server is in control of another party, for an already existing app, or if there are technical reasons preventing the server from serving https connections.
You should use forward secrecy exceptions when the server is unable to support the most modern https protocols.
The ATS accepted by default protocols are the following:
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
If your server supports https with these protocols, and the certificates are properly configured, and the TLS version is 1.2, no App Transport Security configuration needs to be added to the info.plist file.

I found the solution its because of the new app transport security.You need to add NSAppTransportSecurity key to the Info.plist as a dictionary with NSAllowsArbitraryLoads property set to true.
And it should work fine now more here NSURLSession changes in iOS9

Related

OpenTok CreateSession "Error with request submission"

Since 31th July 2018 it doesnt work.
When I tried to create a new session id, the exception return below error:
"Error with request submission".
var Session = OpenTok.CreateSession(mediaMode: MediaMode.ROUTED);
I've tried this link as the web developer site indicates, and everything is ok.
https://support.tokbox.com/hc/en-us/articles/360000046059-Desupporting-TLS-1-0
I'm using .net 4.5.2 and opentok api Version=2.4.6431.26897
Any idea?
Thanks a lot
TokBox Developer Evangelist here.
We disabled support for TLS 1.0 on August 1st which is what your issue looks like.
Please confirm that you're not using TLS 1.0 on your production environment.
You can also force TLS1.2 by adding the following:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Resolved:
I put this in global.asax Application_Start.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Manik is right.
CreateSession fails at app start.
You must configure your app to use only TLS 1.2.
As of 6/6/19 the OpenTok .NET samples are broken unless you make this change.
OpenTok /.NET samples
https://github.com/opentok/Opentok-.NET-SDK
add to OpenTokService.cs:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12
Example: Create a demo account. make changes to the app.config for your API_KEY and API_SECRET
HelloWorld sample project will fail (at startup) with "System.Net.Sockets.SocketException: 'An existing connection was forcibly closed by the remote host'" deep in the CreateSession Call.
in CreateSession -> Post -> DoRequest -> SendData ->SetRequestStream and then about 22 more stack levels down.

Is there a way I can add basic auth to the proxy when I'm using reqwest's client builder?

I'm trying to use Reqwest's proxy feature to pass user:pass basic auth with the rest of the URL into the proxy function. Apparently, the way this crate works basic auth can't be passed this way for the proxy.
When I commented out proxy I got my data but it didn't go through my proxy:
let raw_proxy = format!("https://{}:{}#{}", username, password, forward_proxy);
let proxy = reqwest::Proxy::all(&raw_proxy).unwrap();
let mut buf = &mut Vec::new();
File::open("../cert.der").unwrap().read_to_end(&mut buf).unwrap();
let cert = reqwest::Certificate::from_der(&buf).unwrap();
let client = reqwest::Client::builder()
.add_root_certificate(cert)
//.proxy(proxy)
.build().unwrap();
let mut res = client.post("http://httpbin.org/post")
.header(ContentType::json())
.body(format!("{}", redacted_data))
.send().unwrap();
Short answer is you cannot without writing more code. For the longer answer see this ticket I opened 2 years back. https://github.com/hyperium/hyper/issues/531
Basically, authenticated proxies do not work currently. The headers are not being updated.
The author is supportive, it is just not a high priority. I stopped being behind a proxy so it stopped being one for me too.
If you are using the latest reqwest version, this problem already solved. You need to make sure if your are using HTTP or HTTPS. To double check whether it's connecting to proxy or not, you can use tools like Burp.
I wrote the full-guide on how to setup and test proxy, self-signed certification and Burp for reqwest in here https://www.yodiw.com/rust-reqwest-via-proxy-and-ssl-certificate-captured-by-burp/

Xamarin Forms app, HttpClient seemingly caching responses FOREVER

I'm in the testing phase of my first Xamarin.Forms app, which relies heavily on the HttpClient to retrieve JSON data from a remote site. I've found that once a request has been made, the response seems to be cached and updated data is never retrieved. I'm initializing the HttpClient like this:
new HttpClient()
{
Timeout = new TimeSpan(0, 0, 1, 0),
DefaultRequestHeaders =
{
CacheControl = CacheControlHeaderValue.Parse("no-cache, no-store, must-revalidate"),
Pragma = { NameValueHeaderValue.Parse("no-cache")}
}
}
Those request headers didn't seem to help at all. If I put one of the URLs in my browser, I get the JSON response with the updated data. The server side is setting a no-cache header as well.
Any idea how I can FORCE a fresh request each time? TIA. This testing is being done in an Android emulator, btw. I don't know yet whether the iOS build is behaving similarly.
I'd suggest you use the modernhttpclient nuget package, and implement your android code like:
var httpClient = new HttpClient(new NativeMessageHandler());
This code works on both android, iOS and/or code in a PCL. Basically this nuget package makes sure that you are using the latest platform optimizations for the HttpClient. For Android this is the OkHttp-package, for iOS this is NSURLSession.
This helps you prevent any of the quirks of the provided HttpClient class, and use the optimizations that the platform you're running offers you.
Issues like the one you show should no longer happen.

Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."

I have an application which works fine on Xcode6-Beta1 and Xcode6-Beta2 with both iOS7 and iOS8. But with Xcode6-Beta3, Beta4, Beta5 I'm facing network issues with iOS8 but everything works fine on iOS7. I get the error "The network connection was lost.". The error is as follows:
Error: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo=0x7ba8e5b0 {NSErrorFailingURLStringKey=, _kCFStreamErrorCodeKey=57, NSErrorFailingURLKey=, NSLocalizedDescription=The network connection was lost., _kCFStreamErrorDomainKey=1, NSUnderlyingError=0x7a6957e0 "The network connection was lost."}
I use AFNetworking 2.x and the following code snippet to make the network call:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setSecurityPolicy:policy];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:<example-url>
parameters:<parameteres>
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#“Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
I tried NSURLSession but still receive the same error.
Restarting the simulator fixed the issue for me.
We had this exact error and it turned out to be an issue with the underlying HTTP implementation of NSURLRequest:
As far as we can tell, when iOS 8/9/10/11 receive an HTTP response with a Keep-Alive header, it keeps this connection to re-use later (as it should), but it keeps it for more than the timeout parameter of the Keep-Alive header (it seems to always keep the connection alive for 30 seconds.)
Then when a second request is sent by the app less than 30 seconds later, it tries to re-use a connection that might have been dropped by the server (if more than the real Keep-Alive has elapsed).
Here are the solutions we have found so far:
Increase the timeout parameter of the server above 30 seconds. It looks like iOS is always behaving as if the server will keep the connection open for 30 seconds regardless of the value provided in the Keep-Alive header. (This can be done for Apache by setting the KeepAliveTimeout option.
You can simply disable the keep alive mechanism for iOS clients based on the User-Agent of your app (e.g. for Apache: BrowserMatch "iOS 8\." nokeepalive in the mod file setenvif.conf)
If you don't have access to the server, you can try sending your requests with a Connection: close header: this will tell the server to drop the connection immediately and to respond without any keep alive headers. BUT at the moment, NSURLSession seems to override the Connection header when the requests are sent (we didn't test this solution extensively as we can tweak the Apache configuration)
For mine, Resetting content and settings of Simulator works.
To reset the simulator follow the steps:
iOS Simulator -> Reset Content and Settings -> Press Reset (on the
warning which will come)
The iOS 8.0 simulator runtime has a bug whereby if your network configuration changes while the simulated device is booted, higher level APIs (eg: CFNetwork) in the simulated runtime will think that it has lost network connectivity. Currently, the advised workaround is to simply reboot the simulated device when your network configuration changes.
If you are impacted by this issue, please file additional duplicate radars at http://bugreport.apple.com to get it increased priority.
If you see this issue without having changed network configurations, then that is not a known bug, and you should definitely file a radar, indicating that the issue is not the known network-configuration-changed bug.
Also have a problem with beta 5 and AFNetworking 1.3 when running on iOS 8 simulator that results in a connection error:
Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
The same code works fine on iOS 7 and 7.1 simulators and my debugging proxy shows that the failure occurs before a connection is actually attempted (i.e. no requests logged).
I have tracked the failure to NSURLConnection and reported bug to Apple. See line 5 in attached image:
.
Changing to use https allows connection from iOS 8 simulators albeit with intermittent errors.
Problem is still present in Xcode 6.01 (gm).
I was experiencing this problem while using Alamofire. My mistake was that I was sending an empty dictionary [:] for the parameters on a GET request, rather than sending nil parameters.
Hope this helps!
Opening Charles resolved the issue for me, which seems very strange...
Charles is an HTTP proxy / HTTP monitor / Reverse Proxy that enables a developer to view all of the HTTP and SSL / HTTPS traffic between their machine and the Internet. This includes requests, responses and the HTTP headers (which contain the cookies and caching information).
what solved the problem for me was to restart simulator ,and reset content and settings.
See pjebs comment on Jan 5 on Github.
Method1 :
if (error.code == -1005)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
dispatch_group_t downloadGroup = dispatch_group_create();
dispatch_group_enter(downloadGroup);
dispatch_group_wait(downloadGroup, dispatch_time(DISPATCH_TIME_NOW, 5000000000)); // Wait 5 seconds before trying again.
dispatch_group_leave(downloadGroup);
dispatch_async(dispatch_get_main_queue(), ^{
//Main Queue stuff here
[self redoRequest]; //Redo the function that made the Request.
});
});
return;
}
Also some suggests to re-connect to the site,
i.e. Firing the POST request TWICE
Solution: Use a method to do connection to the site, return (id), if the network connection was lost, return to use the same method.
Method 2
-(id) connectionSitePost:(NSString *) postSender Url:(NSString *) URL {
// here set NSMutableURLRequest => Request
NSHTTPURLResponse *UrlResponse = nil;
NSData *ResponseData = [[NSData alloc] init];
ResponseData = [NSURLConnection sendSynchronousRequest:Request returningResponse:&UrlResponse error:&ErrorReturn];
if ([UrlResponse statusCode] != 200) {
if ([UrlResponse statusCode] == 0) {
/**** here re-use method ****/
return [self connectionSitePost: postSender Url: URL];
}
} else {
return ResponseData;
}
}
On 2017-01-25 Apple released a technical Q&A regarding this error:
Apple Technical Q&A QA1941
Handling “The network connection was lost” Errors
A: NSURLErrorNetworkConnectionLost is error -1005 in the NSURLErrorDomain error domain, and is displayed to users as “The network connection was lost”. This error means that the underlying TCP connection that’s carrying the HTTP request disconnected while the HTTP request was in progress (see below for more information about this). In some circumstances NSURLSession may retry such requests automatically (specifically, if the request is idempotent) but in other circumstances that’s not allowed by the HTTP standards.
https://developer.apple.com/library/archive/qa/qa1941/_index.html#//apple_ref/doc/uid/DTS40017602
I was getting this error as well, but on actual devices rather than the simulator. We noticed the error when accessing our heroku backend on HTTPS (gunicorn server), and doing POSTS with large bodys (anything over 64Kb). We use HTTP Basic Auth for authentication, and noticed the error was resolved by NOT using the didReceiveChallenge: delegate method on NSURLSession, but rather baking in the Authentication into the original request header via adding Authentiation: Basic <Base64Encoded UserName:Password>. This prevents the necessary 401 to trigger the didReceiveChallenge: delegate message, and the subsequent network connection lost.
I had the same problem. I don't know how AFNetworking implements https request, but the reason for me is the NSURLSession's cache problem.
After my application tracking back from safari and then post a http request, "http load failed 1005" error will appear.
If I stop using "[NSURLSession sharedSession]", but to use a configurable NSURLSession instance to call "dataTaskWithRequest:" method as follow, the problem is solved.
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
config.URLCache = nil;
self.session = [NSURLSession sessionWithConfiguration:config];
Just remember to set config.URLCache = nil;.
I have this issue also, running on an iOS 8 device.
It is detailed some more here and seems to be a case of iOS trying to use connections that have already timed out.
My issue isn't the same as the Keep-Alive problem explained in that link, however it seems to be the same end result.
I have corrected my problem by running a recursive block whenever I receive an error -1005 and this makes the connection eventually get through even though sometimes the recursion can loop for 100+ times before the connection works, however it only adds a mere second onto run times and I bet that is just the time it takes the debugger to print the NSLog's for me.
Here's how I run a recursive block with AFNetworking:
Add this code to your connection class file
// From Mike Ash's recursive block fixed-point-combinator strategy https://gist.github.com/1254684
dispatch_block_t recursiveBlockVehicle(void (^block)(dispatch_block_t recurse))
{
// assuming ARC, so no explicit copy
return ^{ block(recursiveBlockVehicle(block)); };
}
typedef void (^OneParameterBlock)(id parameter);
OneParameterBlock recursiveOneParameterBlockVehicle(void (^block)(OneParameterBlock recurse, id parameter))
{
return ^(id parameter){ block(recursiveOneParameterBlockVehicle(block), parameter); };
}
Then use it likes this:
+ (void)runOperationWithURLPath:(NSString *)urlPath
andStringDataToSend:(NSString *)stringData
withTimeOut:(NSString *)timeOut
completionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
OneParameterBlock run = recursiveOneParameterBlockVehicle(^(OneParameterBlock recurse, id parameter) {
// Put the request operation here that you want to keep trying
NSNumber *offset = parameter;
NSLog(#"--------------- Attempt number: %# ---------------", offset);
MyAFHTTPRequestOperation *operation =
[[MyAFHTTPRequestOperation alloc] initWithURLPath:urlPath
andStringDataToSend:stringData
withTimeOut:timeOut];
[operation setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation *operation, id responseObject) {
success(operation, responseObject);
}
failure:^(AFHTTPRequestOperation *operation2, NSError *error) {
if (error.code == -1005) {
if (offset.intValue >= numberOfRetryAttempts) {
// Tried too many times, so fail
NSLog(#"Error during connection: %#",error.description);
failure(operation2, error);
} else {
// Failed because of an iOS bug using timed out connections, so try again
recurse(#(offset.intValue+1));
}
} else {
NSLog(#"Error during connection: %#",error.description);
failure(operation2, error);
}
}];
[[NSOperationQueue mainQueue] addOperation:operation];
});
run(#0);
}
You'll see that I use a AFHTTPRequestOperation subclass but add your own request code. The important part is calling recurse(#offset.intValue+1)); to make the block be called again.
If the problem is occurring on a device, check if traffic is going through a proxy (Settings > Wi-Fi > (info) > HTTP Proxy). I had my device setup to use with Charles, but forgot about the proxy. Seems that without Charles actually running this error occurs.
I was connecting via a VPN. Disabling the VPN solved the problem.
I had same problem. Solution was simple, I've set HTTPBody, but haven't set HTTPMethod to POST. After fixing this, everything was fine.
I had to exit XCode, delete DerivedData folder contents (~/Library/Developer/Xcode/DerivedData or /Library/Developer/Xcode/DerivedData) and exit simulator to make this work.
If anyone is getting this error while uploading files to a backend server, make sure the receiving server has a maximum content size that is allowable for your media. In my case, NGINX required a higher client_max_body_size. NGINX would reject the request before the uploading was done so no error code came back.
I was hitting this error when passing an NSURLRequest to an NSURLSession without setting the request's HTTPMethod.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlComponents.URL];
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
Add the HTTPMethod, though, and the connection works fine
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlComponents.URL];
[request setHTTPMethod:#"PUT"];
I was facing the same issue,
I have enabled Network Link Conditioner for slow network testing for the app. That was creating this error some times,
When i have disabled it from Settings > Developer > Network Link Conditioner, it solved my problem.
Hope this help someone.
On top of all the answers i found one nice solution. Actually The issue related to network connection fail for iOS 12 onword is because there is a bug in the iOS 12.0 onword. And it Yet to resolved. I had gone through the git hub community for AFNetworking related issue when app came from background and tries to do network call and fails on connection establish. I spend 3 days on this and tries many things to get to the root cause for this and found nothing. Finally i got some light in the dark when i red this blog https://github.com/AFNetworking/AFNetworking/issues/4279
It is saying that there is a bug in the iOS 12. Basically you cannot expect a network call to ever complete if the app os not in foreground. And due to this bug the network calls get dropped and we get network fails in logs.
My best suggestion to you is provide some delay when your app are coming from background to foreground and there is network call. Make that network call in the dispatch async with some delay. You'll never get network call drop or connection loss.
Do not wait for Apple to let this issue solve for iOS 12 as its still yet to fix.
You may go with this workaround by providing some delay for your network request being its NSURLConnection, NSURLSession or AFNetworking or ALAMOFIRE. Cheers :)
I was having this issue for the following reason.
TLDR: Check if you are sending a GET request that should be sending the parameters on the url instead of on the NSURLRequest's HTTBody property.
==================================================
I had mounted a network abstraction on my app, and it was working pretty well for all my requests.
I added a new request to another web service (not my own) and it started throwing me this error.
I went to a playground and started from the ground up building a barebones request, and it worked. So I started moving closer to my abstraction until I found the cause.
My abstraction implementation had a bug:
I was sending a request that was supposed to send parameters encoded in the url and I was also filling the NSURLRequest's HTTBody property with the query parameters as well.
As soon as I removed the HTTPBody it worked.
Whenever got error -1005 then need to call API Again.
AFHTTPRequestOperationManager *manager =
[AFHTTPRequestOperationManager manager];
[manager setSecurityPolicy:policy];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:<example-url>
parameters:<parameteres>
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#“Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
if (error.code == -1005) {
// Call method again...
}
}];
You need to Add your code to call function again. MakeSure that you were call method once otherwise its call recursive loop.
I faced the same issue while calling using my company's server from iOS 12 app with a physical device. The problem was that the server hard disk was full. Freeing space in the server solved the problem.
I found the same error in another situation I think due to a timeout not parametrizable through the standard Networking API provided by Apple (URLSession.timeoutIntervalForRequest and URLSession.timeoutIntervalForResource). Even there.. made server answer faster solved the problem
This might be a problem of the parameter that you are passing to request body. I was also facing the same issue. But then I came across CMash's answer here https://stackoverflow.com/a/34181221/5867445 and I changed my parameter and it works.
Issue in a parameter that I was passing is about String Encoding.
Hope this helps.
My problem was on the server. I was using Python's BaseHTTPRequestHandler class and I wasn't sending a body in the response. My problem was solved when I put an empty body like the following.
def do_POST(self):
content_len = int(self.headers.get('Content-Length'))
post_body = self.rfile.read(content_len)
msg_string = post_body.decode("utf-8")
msg_json = json.loads(msg_string)
self.send_response(200)
self.end_headers() #this and the following lines were missing
self.wfile.write(b'')
I had the same issue, the problem was bug of Alomofire and NSUrlSession. When you returning back to app from safari or email you need to wait nearly 2 seconds to do you network response via Alamofire
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
Your network response
}
Got the issue for months, and finally discovered that when we disable DNSSEC on our api domain, everything was ok.

Phonegap Android app ajax requests to HTTPS fail with status 0

Ajax HTTPS requests from my PhoneGap/Cordova app on Android inexplicably fail with status=0. It appears only when signing the app with the release key (i.e., exporting from ADT), but doesn't appear when signing with debug key (running directly in emulator or phone).
request = new XMLHttpRequest()
request.open "GET", "https://some.domain/", true
request.onreadystatechange = ->
console.log "** state = " + request.readyState
if request.readyState is 4
console.log "** status = " + request.status
request.send()
always outputs
** state = 4
** status = 0
It doesn't matter if i install the app from Play Store or with adb utility. I presume it could be connected with the certificate, since not all HTTPS domains fail this way.
I was having the same problem but my solution was a little different.
In only the Android App build of my Cordova app, AJAX calls to my server via HTTPS were being blocked. Not in iOS, not in desktop browsers. Most confusingly, in the actual Android Browser the HTTPS AJAX calls would work no problem.
I verified that I could make HTTPS AJAX calls to well known and trusted URLs such as https://google.com as well as regular HTTP calls to any URL I cared to try.
This led me to believe that my SSL cert was either NOT installed 100% correctly OR the cheap (~$10 usd) cert from PositveSSL was not universally trusted OR both.
My cert was installed on my AWS Load Balancer so I looked around about how I may have messed this up and also how PositiveSSL was not the best cert to be using in terms of trustworthiness. Lucky me found an article covering AWS ELB installation of certs AND they happened to be using a PositiveSSL cert! Contained within was this little gem:
"...Don’t be fooled by the AWS dialog, the certificate chain isn’t really optional when your ELB is talking directly to a browser..."
http://www.nczonline.net/blog/2012/08/15/setting-up-ssl-on-an-amazon-elastic-load-balancer/
Drumroll....
I reinstalled the cert with the "optional" Certificate Chain info and voilà!, the HTTPS AJAX calls to my server started working.
So it appears that the Android Webview is more conservative than the Android Browser in terms of cert trust. This is not totally intuitive since they are supposed to be basically the same tech.
It happens when the requested URL responds with an erroneous or self-signed certificate. While testing or distributing the app to friends, setting <application android:debuggable="true"...> in AndroidManifest.xml is enough — it automatically bypasses certificate errors.
But Google Play Store will not accept an APK with android:debuggable="true". First of all, the certificates, of course, need to be fixed. But while that happens, here is a workaround for PhoneGap/Cordova 3:
In your app package create a subclass for CordovaWebViewClient:
public class SSLAcceptingCordovaWebViewClient extends CordovaWebViewClient {
public SSLAcceptingCordovaWebViewClient(CordovaInterface cordova, CordovaWebView view) {
super(cordova, view);
}
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
}
Same for IceCreamCordovaWebViewClient:
public class SSLAcceptingIceCreamCordovaWebViewClient extends IceCreamCordovaWebViewClient {
public SSLAcceptingIceCreamCordovaWebViewClient(CordovaInterface cordova, CordovaWebView view) {
super(cordova, view);
}
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
}
in <Your App Name>.java add an override for makeWebViewClient:
#Override
protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) {
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
return new SSLAcceptingCordovaWebViewClient(this, webView);
} else {
return new SSLAcceptingIceCreamCordovaWebViewClient(this, webView);
}
}
Et voilà! SSL errors will be disregarded. However, never use erroneous certificates. Try to fix them first and use this dirty workaround only when you run out of other solutions.
The other option that works as well is to recompile the underlying cordova.jar file so that the test is removed completely thus no reason to worry about your cert being valid or not. I ran in the issue due to the fact that Android would not recognize the GoDaddy cert that was on the server. The cert shows valid on iOS but even when browsing from Android complained about the cert. This is from the 2.9.x branch as this is what I was working with.
cordova-android / framework / src / org / apache / cordova / CordovaWebViewClient.java
#TargetApi(8)
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final String packageName = this.cordova.getActivity().getPackageName();
final PackageManager pm = this.cordova.getActivity().getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
handler.proceed();
return;
/* REMOVED TO BY PASS INVALID CERT CHAIN ****
if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// debug = true
handler.proceed();
return;
} else {
// debug = false
super.onReceivedSslError(view, handler, error);
}*/
} catch (NameNotFoundException e) {
// When it doubt, lock it out!
super.onReceivedSslError(view, handler, error);
}
}
NOTE: I understand this is not safe but when all else fails this solved the issue that has been on going for over 2 months including reinstalling the cert following the cert chain install guide and beside it is a site that is our own not 3rd party so no matter if valid or not it is only connecting to this server.
In my case it has been a missing intermediate certificate, which I had to install on my webserver. You have to keep it in mind especially when you use cheap certificates.
You can check it easily online if your certificate chain is proper, you will find a lot on google, e.g. https://www.sslshopper.com/ssl-checker.html
At the Apache2 it's part of the VirtualHost 443 directive, you have three rules in your directive, it looks like that:
SSLCertificateFile /etc/apache2/ssl/mycert.crt
SSLCertificateKeyFile /etc/apache2/ssl/mykey.key
SSLCertificateChainFile /etc/apache2/ssl/certification_auth_intermediate.crt
You can't use relese-ready (phonegap) apks with self-signed certificates. Look at this answer to get further information.
lg
fastrde

Resources