{ "id": "149117", "key": "TIMOB-19069", "fields": { "issuetype": { "id": "2", "description": "A new feature of the product, which has yet to be developed.", "name": "New Feature", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [], "resolution": null, "resolutiondate": null, "created": "2015-06-25T03:15:44.000+0000", "epic": { "id": 149396, "key": "TIMOB-19145", "name": "iOS: iOS 9 Updates", "summary": "iOS: iOS9 Updates", "color": { "key": "color_1" }, "done": false }, "priority": { "name": "High", "id": "2" }, "labels": [ "appthinning" ], "versions": [], "issuelinks": [ { "id": "48286", "type": { "id": "10002", "name": "Duplicate", "inward": "is duplicated by", "outward": "duplicates" }, "inwardIssue": { "id": "148974", "key": "TIMOB-19049", "fields": { "summary": "iOS9: investigate how best to support App Thinning", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "None", "id": "6" }, "issuetype": { "id": "7", "description": "gh.issue.story.desc", "name": "Story", "subtask": false } } } }, { "id": "49596", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "133680", "key": "TIMOB-17391", "fields": { "summary": "Android: Support APK expansion files", "status": { "description": "The issue is open and ready for the assignee to start work on it.", "name": "Open", "id": "1", "statusCategory": { "id": 2, "key": "new", "colorName": "blue-gray", "name": "To Do" } }, "priority": { "name": "Medium", "id": "3" }, "issuetype": { "id": "2", "description": "A new feature of the product, which has yet to be developed.", "name": "New Feature", "subtask": false } } } }, { "id": "48346", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "inwardIssue": { "id": "148692", "key": "TIMOB-18998", "fields": { "summary": "iOS9: App thinning: Create XCAssets (imagesets) w/ the cli and access resources within those catalogs at runtime", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "High", "id": "2" }, "issuetype": { "id": "2", "description": "A new feature of the product, which has yet to be developed.", "name": "New Feature", "subtask": false } } } } ], "assignee": null, "updated": "2018-10-03T11:07:58.000+0000", "status": { "description": "The issue is open and ready for the assignee to start work on it.", "name": "Open", "id": "1", "statusCategory": { "id": 2, "key": "new", "colorName": "blue-gray", "name": "To Do" } }, "components": [ { "id": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "*Overview:*\r\nThe On-Demand-Resources provide a way to load resources only when requested. The resources are grouped into tags, which is done through Xcode (also need to figure out, how to do this on proxy side). The Idea is, to supply an easy way to access and download resources and release them after there are not needed anymore as part of the app thinning process. The current progress can also be tracked, as well as warnings regarding low memory. \r\n\r\n*Demo code:*\r\n{code}\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor: \"#fff\",\r\n layout: \"vertical\"\r\n});\r\n\r\nvar manager = Ti.App.iOS.createOnDemandResourcesManager();\r\n\r\nvar beginButton = Ti.UI.createButton({\r\n title: \"Access Resources\",\r\n top: 50\r\n});\r\n\r\nvar resultProgress = Ti.UI.createProgressBar({\r\n top: 50,\r\n min: 0,\r\n max: 1,\r\n width: 300,\r\n height: 10,\r\n value: 0.0\r\n});\r\n\r\nvar resultImage = Ti.UI.createImageView({\r\n top: 50,\r\n height: 100,\r\n image: \"titanium.png\"\r\n});\r\n\r\nbeginButton.addEventListener(\"click\", function() {\r\n manager.conditionallyBeginAccessingResources({\r\n tags: [\"appc\"],\r\n success: function(e) {\r\n resultImage.setImage(\"titanium\");\r\n // Resources are now accessible.\r\n Ti.API.warn(e);\r\n },\r\n error: function(e) {\r\n // Accessing the resources failed.\r\n Ti.API.error(e);\r\n }\r\n });\r\n});\r\n\r\nmanager.addEventListener(\"progress\", function(e) {\r\n Ti.API.warn(\" -- PROGRESS --\");\r\n Ti.API.warn(e);\r\n resultProgress.setValue(e.value);\r\n});\r\n\r\nwin.add(beginButton);\r\nwin.add(resultProgress);\r\nwin.add(resultImage);\r\nwin.open();\r\n{code}\r\n\r\n*Apple docs:* https://developer.apple.com/library/prerelease/ios/documentation/FileManagement/Conceptual/On_Demand_Resources_Guide/\r\n\r\n*Note:*\r\nOn demand resources are only available for iOS9. that means for developers who wants this, they have to set the minimum iOS version as 9.0 otherwise it won't compile. Just do this in tiapp.xml.\r\n{code}\r\n\r\n 9.0\r\n\r\n{code}", "attachment": [], "flagged": false, "summary": "IOS9: App thinning: Support on-demand resources for app thinning", "creator": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "environment": null, "comment": { "comments": [ { "id": "357384", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "The documentation link was updated by Apple yesterday, so i updated here as well. Also added a brief overview, how the implementation will look.\r\n\r\n[~cng]: The tagging of resources is currently a problem, because resources can only be assigned to tags through Xcode. How could we solve this?", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2015-07-09T20:41:28.000+0000", "updated": "2015-07-09T20:41:28.000+0000" }, { "id": "360641", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Once we have generating image asset catalogs in place we could have a Titanium-specific file where developers would list filepaths per tag. Then we can use that when we generate asset catalogs to set the tags for each of them.", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2015-08-21T06:59:30.000+0000", "updated": "2015-08-21T06:59:30.000+0000" }, { "id": "360781", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Could we achieve parity with Android's Google Play Expansion files? [~jasonkneen] has a (closed source) module for that: https://github.com/jasonkneen/TiExpansionFiles", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2015-08-22T10:42:56.000+0000", "updated": "2015-08-22T10:42:56.000+0000" }, { "id": "365715", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "[~hansknoechel] have you looked into android expansion files (see earlier comment) as well? With a 100mb limit (earlier 50) this is even more needed for Android then iOS.", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2015-10-03T07:34:17.000+0000", "updated": "2015-10-03T07:34:17.000+0000" }, { "id": "366490", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "[~hansknoechel] just an idea.. why not let developers store assets they want on-demand in a separate directory? Then just by looking at the directory tree you can see which assets are on-demand and which are not. And then we don't need any Studio UI as well.", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2015-10-12T08:37:39.000+0000", "updated": "2015-10-12T08:37:39.000+0000" }, { "id": "366655", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Because it's a bit more complicated: We must be able to assign certain certain files to groups (aka \"tags\"), that can then be accessed. So we cannot access per file but per tag. Example: file1,file2 are part of \"mytag_1\" and file3,file4 are part of \"mytag_2\". \r\n\r\nTherefore we need a Xcode similar interface to tag files to support it the right way. ", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2015-10-13T15:30:24.000+0000", "updated": "2015-10-13T15:30:24.000+0000" }, { "id": "366656", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Ah.... (y)", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2015-10-13T15:35:33.000+0000", "updated": "2015-10-13T15:35:33.000+0000" }, { "id": "368592", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "[~hansknoechel] as you start to think of a meta-file and CLI (then later Studio) tooling to tag files, could you right form the start also think about parity with Android APK Expansion Files?\r\n\r\nTIMOB-17391\r\n\r\n[~jasonkneen] used to have a (closed source) module for this on GitHub but I see it's no longer.", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2015-11-02T08:31:45.000+0000", "updated": "2015-11-02T08:31:45.000+0000" }, { "id": "400459", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "/cc [~cng], [~cbarber], [~sdavenport]\r\nI talked to [~jasonkneen] and he was so kind to provide the Android source for Android APK Expansion Files that we can include in our {{Ti.Filesystem}} core to access the downloaded extension files (basically just a zip that needs some file handling from what I saw). \r\n\r\nIn addition to that, we have this (finished) iOS PR to support iOS On-Demand-Resources. The current problem was that we need a data structure to group the resources in \"tags\" so we can request them from our apps. For that, I thought about an architecture like this (in the {{}} group:\r\n\r\n{code:xml}\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n{code}\r\n\r\n\"Tags\" can have multiple \"files\" that are placed in the asset catalog. Currently, I think, we only store JPG and PNG i files in the asset catalog, that regex needs to be updated and allow to create a {{dataset}} along with the existing {{imageset}} to allow mp3 files and other non-image data as well. The {{Contents.json}} for those sets (e.g. {{Assets.xcassets/my_music.dataset}} looks like the following:\r\n{code:json}\r\n{\r\n \"info\" : {\r\n \"version\" : 1,\r\n \"author\" : \"xcode\"\r\n },\r\n \"data\" : [\r\n {\r\n \"idiom\" : \"universal\",\r\n \"filename\" : \"my_music.mp3\"\r\n }\r\n ]\r\n}\r\n{code}\r\n\r\nA summary of all different kind of sets:\r\n\r\n||Type||Extension||\r\n|Image Sets|.imageset|\r\n|Data Sets|.dataset|\r\n|Texture Sets|.textureset|\r\n|Cube Texture Sets|.cubetextureset|\r\n\r\nWe would only need support for the first two, as the latter require more CLI logic like X-Y-Z parts.\r\n\r\nWe also need the following CLI adjustments:\r\n- Parse the {{on-demand-resources}} node to create an internal data structure of tags and files\r\n- Map the file names to our used SHA-1 hashes (or even get rid of that if possible by now, solves some more problems as well)\r\n- Use the mapped data structure to adjust the {{.pbxproj}} so Xcode knows how we group our files, like this:\r\n{code}\r\n29B97313FDCFA39411CA2CEA /* Project object */ = {\r\n isa = PBXProject;\r\n attributes = {\r\n KnownAssetTags = (\r\n\t level1,\r\n\t);\r\n\tLastUpgradeCheck = 0430;\r\n };\r\n ...\r\n}\r\n{code}\r\n- Finally, link the tags to the toplevel {{Assets.xcassets/Contents.json}} as proposed above:\r\n{code:json}\r\n\"info\" : {\r\n ...\r\n \"on-demand-resource-tags\" : [\r\n \"level1\"\r\n ]\r\n}\r\n{code}\r\n\r\nI could think about 6.1.0 or 6.2.0 include this change, it would be a major Enterprise feature for reducing app size and exposing more flexibility across asset management. Thoughts welcome!", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-11-06T11:27:53.000+0000", "updated": "2016-11-06T18:12:08.000+0000" }, { "id": "400497", "author": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "body": "Couple of thoughts:\r\n\r\n# I don't want to continue polluting the {{tiapp.xml}} with more and more garbage. We need to ditch the {{tiapp.xml}} as a project file and come up with a proper project file similar to Xcode's. What you're talking about is assigning metadata to individual files and we need this for so many things beyond asset catalog such as encryption. We need a project file that supports proper build configurations (see TIMOB-12025 and https://wiki.appcelerator.org/display/pe/Build+Configurations) because we cannot continue to tightly couple things to the deploy type and app guid.\r\n# I don't love that we have to SHA resource paths, but it works and works well. Perhaps we should just convert the resource path to something readable such as the path where the path separate is underscores?\r\n# What about Android and Windows? I'm not sure what this APK expansion buys us beyond larger apps. Doesn't Android have a similar concept to app thinning? How about Windows? It would be great to design a system that abstracts the asset catalog (cough, Titanium asset catalog, cough) and that works for all platforms.", "updateAuthor": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "created": "2016-11-07T14:25:57.000+0000", "updated": "2016-11-07T14:26:08.000+0000" }, { "id": "400505", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "In response:\r\n# Agree. We introduced the [appc.js|https://github.com/appcelerator/hyperloop-examples/blob/master/appc.js] with Hyperloop, maybe that's a good place to store them JS-based (please no more XML :-)\r\n# What have been the problems with base names instead of hashes again? Densities go under one base name (file.png, file@2x.png, file@3x.png), same base names (e.g. file.png and file.mp3) go into different sets (.imageset vs .dataset). And if there is an edge-case like file.png vs file.jpg, we would throw a warn-log and hash the names. But let me check the native behavior first, pretty sure the handle this with \"file-1\" then. *EDIT*: [Yes|https://abload.de/img/screenshot2016-11-07azask9.png] it [does|https://abload.de/img/screenshot2016-11-07aecsfh.png].\r\n# Looking at [this article|https://arc.applause.com/2015/09/28/android-6-0-apk-file-size/], APK expansion files are the equivalent for iOS on demand resources. For Windows, I could not find anything similar, maybe the Windows team knows more regarding that. ", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-11-07T17:12:26.000+0000", "updated": "2016-11-07T17:16:00.000+0000" } ], "maxResults": 15, "total": 15, "startAt": 0 } } }