{ "id": "132398", "key": "AC-910", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "12217", "key": "AC", "name": "Appcelerator - INBOX", "projectCategory": { "id": "10000", "description": "", "name": "Customer Service" } }, "resolution": { "id": "2", "description": "The problem described is an issue which will never be fixed.", "name": "Won't Fix" }, "resolutiondate": "2014-07-02T16:52:11.000+0000", "created": "2014-06-29T16:07:09.000+0000", "labels": [ "XMLHttpRequest", "webview" ], "versions": [], "issuelinks": [], "assignee": { "name": "rtlechuga", "key": "rtlechuga", "displayName": "Radamantis Torres-Lechuga", "active": false, "timeZone": "Asia/Dubai" }, "updated": "2016-03-08T07:37:13.000+0000", "status": { "description": "A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.", "name": "Resolved", "id": "5", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [], "description": "*Overview*\r\nOn Android if I load a local file in a webview and request another local file from the Application Data Directory via XMLHttpRequest() the file fails to load. The xhr status returned remains 0. Is there any way to facilitate this type of request from within a webview to a local resource?\r\n\r\n*Reason for Need*\r\nWe've developed an ePub document reader for iOS with a handful of features similar to iBooks or Kindle. By nature the ePub document needs to render in a WebView. When downloading and loading an ePub document from the web to display in the reader the WebView needs access to the Application Data directory.\r\n\r\n*Expected*\r\nRunning this produces a console output of at lease one Pass test case on an Android device or Similator\r\n\r\n*Observed Results*\r\nAll test paths fail on Android. On iOS this works\r\n\r\n*app.js*\r\n{code:javascript}\r\nvar win = Ti.UI.createWindow();\r\nwin.add(Ti.UI.createWebView({\r\n url : \"/index.html\"\r\n}));\r\n\r\nvar data = Ti.Filesystem.getFile(Ti.Filesystem.getApplicationDataDirectory() + \"/hello.txt\");\r\ndata.write(\"Hello World\");\r\n\r\nvar paths = [];\r\npaths.push(Ti.Filesystem.getApplicationDataDirectory() + \"/hello.txt\");\r\npaths.push(Ti.Filesystem.applicationDataDirectory + \"/hello.txt\");\r\npaths.push(\"/hello.txt\");\r\npaths.push(\"file:///hello.txt\");\r\npaths.push(\"appdata-private:///hello.txt\");\r\n\r\nTi.App.addEventListener('webView:response', function(e) {\r\n if (e.success) {\r\n Ti.API.info(e.args.index + \": Pass [\" + e.response + \"] : \" + e.args.path);\r\n } else {\r\n Ti.API.info(e.args.index + \":Fail : \" + e.args.path);\r\n }\r\n});\r\n\r\nTi.App.addEventListener('webView:runTests', function() {\r\n for (var i = 0; i < paths.length; i++) {\r\n Ti.API.info(\"trying \" + paths[i]);\r\n Ti.App.fireEvent('webView:load', {\r\n path : paths[i],\r\n index : i\r\n });\r\n }\r\n});\r\n\r\nwin.open();\r\n{code}\r\n\r\n*index.html*\r\n{code:javascript}\r\n\r\n \r\n \r\n \r\n\r\n{code}\r\n", "attachment": [], "flagged": false, "summary": "Unable to access ApplicationData file from WebView using an XMLHttpRequest on Android", "creator": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "subtasks": [], "reporter": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "environment": "3.2.3 GA\r\nAlloy 1.4\r\nGoogle Nexus 10 - 4.2.2 - API 17 - 2560x1600", "comment": { "comments": [ { "id": "311711", "author": { "name": "mpmiranda", "key": "mpmiranda", "displayName": "Mauro Parra-Miranda", "active": true, "timeZone": "America/Mexico_City" }, "body": "Hello! \r\n\r\nYou can access it, with a different logic. Check testcase: \r\n\r\n{code}\r\nvar win = Ti.UI.createWindow({\r\n\tbackgroundColor:'#fff'\r\n});\r\n\r\nvar loadingLabel = Ti.UI.createLabel({\r\n\ttext:'Loading ...',\r\n\ttop:20,\r\n\tleft: 10\r\n});\r\nwin.add(loadingLabel);\r\n\r\n\r\nvar xhr = Titanium.Network.createHTTPClient({\r\n\tonload: function() {\r\n\t\t// first, grab a \"handle\" to the file where you'll store the downloaded data\r\n\t\tvar f = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory,'mygraphic.png');\r\n\t\tf.write(this.responseData); // write to the file\r\n\t\tTi.App.fireEvent('graphic_downloaded', {filepath:f.nativePath});\r\n\t},\r\n\ttimeout: 10000\r\n});\r\nxhr.open('GET','http://cloud.appcelerator.net/cb0dbcc6-6fe3-4206-a32e-cf266c80aa3d/default_app_logo.png');\r\nxhr.send();\r\n\r\nTi.App.addEventListener('graphic_downloaded', function(e) {\r\n\r\n\tvar file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory,'mygraphic.png');\r\n\t\r\n\tvar webview = Ti.UI.createWebView({\r\n\t\turl:file.resolve(),\r\n\t});\r\n\twin.remove(loadingLabel);\r\n\twin.add(webview);\r\n});\r\n\r\nwin.open();\r\n{code}\r\n\r\nLet me know if that works for you. \r\n\r\nBest Regards,", "updateAuthor": { "name": "mpmiranda", "key": "mpmiranda", "displayName": "Mauro Parra-Miranda", "active": true, "timeZone": "America/Mexico_City" }, "created": "2014-06-30T22:45:18.000+0000", "updated": "2014-06-30T22:45:18.000+0000" }, { "id": "311746", "author": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "body": "Your example illustrates setting the url of the webview to the file in the applicationDataDirectory. This does not relate to the issue I am trying to illustrate above. The difference is that we are not trying to set the url of the WebView to a file in the applicationDataDirectory (your example). We are trying to read a file from local javascript in the WebView via the XMLHttpRequest to a file that resides in the applicationDataDirectory.\r\n", "updateAuthor": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "created": "2014-07-01T01:02:17.000+0000", "updated": "2014-07-01T01:02:17.000+0000" }, { "id": "311817", "author": { "name": "mpmiranda", "key": "mpmiranda", "displayName": "Mauro Parra-Miranda", "active": true, "timeZone": "America/Mexico_City" }, "body": "Hello [~jerodfritz]! \r\n\r\nWhich one is the usercase for this? Maybe we can provide an alternative solution for the issue. \r\n\r\nBest Regards,", "updateAuthor": { "name": "mpmiranda", "key": "mpmiranda", "displayName": "Mauro Parra-Miranda", "active": true, "timeZone": "America/Mexico_City" }, "created": "2014-07-01T16:45:43.000+0000", "updated": "2014-07-01T16:45:43.000+0000" }, { "id": "311831", "author": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "body": "HI Mauro,\r\n\r\nStated above in the \"Reason For Need\" we have implemented an ePub document reader in iOS that functions very well. In the process of converting to Android we have encountered an issue which I believe is due to a cross domain request issue that I'm hoping there is a workaround for. An ePub document is essentially a zip containing a series of html files. To build any type of reader you must render these html files within a webview. The webview must be capable of loading files stored in the Application's data directory where the epub was downloaded to. The example I provided simulates the types of requests the app must be able to make.\r\n\r\n- Jerod", "updateAuthor": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "created": "2014-07-01T17:27:42.000+0000", "updated": "2014-07-01T17:27:42.000+0000" }, { "id": "311840", "author": { "name": "mpmiranda", "key": "mpmiranda", "displayName": "Mauro Parra-Miranda", "active": true, "timeZone": "America/Mexico_City" }, "body": "Hello [~jerodfritz]!\r\n\r\nIn that case, the recommendation would be take the sample code provided, get the zip within the mobile app and then you can open the webview just for display. \r\n\r\nBest Regards", "updateAuthor": { "name": "mpmiranda", "key": "mpmiranda", "displayName": "Mauro Parra-Miranda", "active": true, "timeZone": "America/Mexico_City" }, "created": "2014-07-01T17:50:14.000+0000", "updated": "2014-07-01T17:50:14.000+0000" }, { "id": "311847", "author": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "body": "Mauro. Thank you for looking into this, but you're still not understanding the problem. Can you take another look at the explanation. ", "updateAuthor": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "created": "2014-07-01T17:59:28.000+0000", "updated": "2014-07-01T17:59:28.000+0000" }, { "id": "311973", "author": { "name": "adriano", "key": "adriano", "displayName": "Adriano Paladini", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Hi Jerod Fritz,\r\n I have a \"e-book reader\" published. Search on Stores for \"Widbook\".\r\n The way I did it was different, I carry a \"model\" (index.html), and inject the contents therein. \r\n Ie: I load the CSS and the text in a ready template. \r\n For this I have a template with html tags that I substitute with REPLACE with the contents of files and load in web view.", "updateAuthor": { "name": "adriano", "key": "adriano", "displayName": "Adriano Paladini", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2014-07-02T00:15:41.000+0000", "updated": "2014-07-02T00:15:41.000+0000" }, { "id": "312074", "author": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "body": "Thanks for the suggestion Adriano. We will explore that route.", "updateAuthor": { "name": "jerodfritz", "key": "jerodfritz", "displayName": "Jerod Fritz", "active": true, "timeZone": "America/New_York" }, "created": "2014-07-02T16:41:02.000+0000", "updated": "2014-07-02T16:41:02.000+0000" }, { "id": "312077", "author": { "name": "rtlechuga", "key": "rtlechuga", "displayName": "Radamantis Torres-Lechuga", "active": false, "timeZone": "Asia/Dubai" }, "body": "The purpose of the XMLHttpRequest or HTTPRequest it's to transfer data between a client and a server, in this particular case, to try to access a local file using http request is something that is unsupported, I'll encourage you to use another approach to access the files that your reader needs. Like the one mentioned by [~mpmiranda] ", "updateAuthor": { "name": "rtlechuga", "key": "rtlechuga", "displayName": "Radamantis Torres-Lechuga", "active": false, "timeZone": "Asia/Dubai" }, "created": "2014-07-02T16:52:11.000+0000", "updated": "2014-07-02T16:52:11.000+0000" } ], "maxResults": 10, "total": 10, "startAt": 0 } } }