Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading local file works fine in simulator but crash on device

Tags:

ios

uiwebview

Using WKWebview for playing local file works on simulator but give me this error on device (iOS 9.2.1)

fail in didFailProvisionalNavigation Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"
UserInfo={NSErrorFailingURLKey=file:///var/mobile/Containers/Data/Application/2FBE4DE6-9441-4C5A-BB1F-8598CA89664C/Documents/courses/agdg_test1455704820291/index.html?jqueryFilePath=file:///var/mobile/Containers/Bundle/Application/5A442D34-3360-46C7-8B28-B6F3AED373CE/elearning.app/view/jquery.js&commandsFilePath=file:///var/mobile/Containers/Bundle/Application/5A442D34-3360-46C7-8B28-B6F3AED373CE/elearning.app/view/commands.js,
_WKRecoveryAttempterErrorKey=<WKReloadFrameErrorRecoveryAttempter: 0x15e295f0>,NSErrorFailingURLStringKey=file:///var/mobile/Containers/Data/Application/2FBE4DE6-9441-4C5A-BB1F-8598CA89664C/Documents/courses/agdg_test1455704820291/index.html?jqueryFilePath=file:///var/mobile/Containers/Bundle/Application/5A442D34-3360-46C7-8B28-B6F3AED373CE/elearning.app/view/jquery.js&commandsFilePath=file:///var/mobile/Containers/Bundle/Application/5A442D34-3360-46C7-8B28-B6F3AED373CE/elearning.app/view/commands.js}

Here is code provisioning the webView :

let lesson:NSMutableArray = courseDB_Manager.getInstance().getRowDB("SELECT * FROM lesson_chapter WHERE lesson_chapter_id = ?", args: [chapterToPlay], structType: "lesson_chapter")
let occ: lesson_chapter_struct = lesson[0] as! lesson_chapter_struct
fileToPlay = Utility.getPath("courses/" + occ.lesson_chapter_fichier)

let commandsFilePath = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("commands", ofType: "js", inDirectory: "view")!, isDirectory: false)
let jqueryFilePath = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("jquery", ofType: "js", inDirectory: "view")!, isDirectory: false)

let target = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("start", ofType: "html", inDirectory: "view")!, isDirectory: false)
let params = "?fileToPlay=" + fileToPlay + "&commandsFilePath=" + String(commandsFilePath) + "&jqueryFilePath=" + String(jqueryFilePath) + "&" + NSUUID().UUIDString
let url = NSURL(string: NSString(string: target.absoluteString + params) as String)
NSURLCache.sharedURLCache().removeAllCachedResponses()
NSURLCache.sharedURLCache().diskCapacity = 0

if(progress.current() != 1) {
    let askForResume = UIAlertController(title: "Resume", message: "Resume ????????????", preferredStyle: UIAlertControllerStyle.Alert)
    askForResume.addAction(UIAlertAction(title: "YES", style: .Default, handler: { (action: UIAlertAction!) in
        self.resume = true
        self.webView.loadFileURL(url!, allowingReadAccessToURL: url!)
    }))
    askForResume.addAction(UIAlertAction(title: "NO", style: .Default, handler: { (action: UIAlertAction!) in
        self.webView.loadFileURL(url!, allowingReadAccessToURL: url!)
    }))
    presentViewController(askForResume, animated: true, completion: nil)
} else {
    self.webView.loadFileURL(url!, allowingReadAccessToURL: url!)
}

After implementing allowingReadAccessToURL i've got this error :

Received an unexpected URL from the web process: 'file:///[...]commands.js'
Received an invalid message "WebPageProxy.DecidePolicyForNavigationAction" from the web process.

it is because, files requested by js are confronted to same issue ?

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
    decisionHandler(WKNavigationActionPolicy.Allow)
}

UPDATE 1 - Resolved in second update

Now, i'm using this code :

let target = NSURL(fileURLWithPath: fileToPlay + "/index.html", isDirectory: false)
let params = "?commandsFilePath=" + String(commandsFilePath) + "&jqueryFilePath=" + String(jqueryFilePath) + "&" + NSUUID().UUIDString
let url = NSURL(string: NSString(string: target.absoluteString + params) as String)

if #available(iOS 9.0, *) {
    self.webView.loadFileURL(url!, allowingReadAccessToURL: url!)
} else {
    do {
        let fileUrl = try self.fileURLForBuggyWKWebView8(url!)
        self.webView.loadRequest(NSURLRequest(URL: fileUrl))
    } catch let error as NSError {
        print("Error: " + error.debugDescription)
    }
}

Whose work fine on simulator (iOS 9), namely, load fileUrl and files included by js code. But on device (also iOS 9), it's load fileUrl and js files included from mainBundle but not js files in same directory of fileUrl

e.g : fileUrl points to

"file:///var/mobile/Containers/Data/Application/4F2A96AF-8E58-41A6-A4D3-A19D254C048F/Documents/courses/agdg_test1455704820291/index.html"

including js files from subdirectory of fileUrl doesn't work

"file:///var/mobile/Containers/Data/Application/4F2A96AF-8E58-41A6-A4D3-A19D254C048F/Documents/courses/agdg_test1455704820291/data/player.js"

But including js files from bundle work's perfectly. I also verified with iPad File Explorer that file /data/player.js exist and it's the case.

UPDATE 2

I resolved this with set allowingReadAccessToURL to entire directory, not only my index file.

Since i use this method for provisioning WKWebView, js code is never finish to buffering sounds/videos to play on device...I don't understand who's the difference that make execution so slow between -[WKWebView loadFileURL:allowingReadAccessToURL:] and [WKWebView loadRequest]

like image 459
Khorwin Avatar asked Jan 06 '23 12:01

Khorwin


1 Answers

In iOS 9 and up, WKWebView has a new method that will do what you want, -[WKWebView loadFileURL:allowingReadAccessToURL:]

Make sure you are loading the local resource with that call.

If you are supporting iOS 8, it get s a little more difficult. See this answer for more details.

like image 138
wottle Avatar answered Jan 30 '23 05:01

wottle