{ "id": "163362", "key": "TIMOB-23935", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "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": [ { "id": "16980", "description": "New V8", "name": "Release 6.0.0", "archived": false, "released": true, "releaseDate": "2016-11-15" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2016-09-29T06:50:28.000+0000", "created": "2016-09-21T18:22:56.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "camera", "iOS", "qe-6.0.0", "switchCamera" ], "versions": [ { "id": "17706", "name": "Release 5.4.0", "archived": false, "released": true, "releaseDate": "2016-08-11" }, { "id": "18253", "name": "Release 5.5.0", "archived": false, "released": true, "releaseDate": "2016-09-13" } ], "issuelinks": [], "assignee": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "updated": "2016-09-29T17:44:46.000+0000", "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" } }, "components": [ { "id": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "Titanium.Media.switchCamera() fails to load the front-facing camera.\r\n\r\n*Steps to Reproduce:*\r\n1.Run Code\r\n{code:javascript}\r\nvar win = Ti.UI.createWindow({\r\n layout: \"vertical\"\r\n});\r\nwin.open();\r\n\r\nvar button = Ti.UI.createButton({\r\n title: \"Camera\",\r\n top: 20,\r\n width: 200,\r\n height: 200\r\n});\r\n\r\nbutton.addEventListener(\"click\", takePics);\r\n\r\nwin.add(button);\r\n\r\nvar view = Ti.UI.createView();\r\n\r\nvar take = Ti.UI.createView({\r\n\r\n bottom: 20,\r\n backgroundColor: \"white\",\r\n width: 70,\r\n height: 70,\r\n borderRadius: 35\r\n\r\n});\r\n\r\nvar switchCamera = Ti.UI.createButton({\r\n\r\n top: 30,\r\n title: \"Switch\",\r\n right: 30,\r\n backgroundColor: \"red\",\r\n width: 50,\r\n height: 50,\r\n borderRadius: 25\r\n\r\n});\r\n\r\n// Add to the parent view.\r\nview.add(take);\r\nview.add(switchCamera);\r\n\r\nfunction takePics() {\r\n Ti.Media.showCamera({\r\n success: function(e) {\r\n Ti.API.info(e.media);\r\n\r\n },\r\n error: function(e) {\r\n alert(e);\r\n },\r\n autohide: false,\r\n overlay: view,\r\n saveToPhotoGallery: true,\r\n mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],\r\n showControls: false\r\n });\r\n\r\n}\r\n\r\ntake.addEventListener('click', function(e) {\r\n Ti.Media.takePicture();\r\n});\r\n\r\n//var value = true;\r\nswitchCamera.addEventListener('click', function() {\r\n\tTi.API.info(\"Switch camera!\");\r\n if (Ti.Media.camera == Ti.Media.CAMERA_FRONT) {\r\n Ti.Media.switchCamera(Ti.Media.CAMERA_REAR);\r\n } else {\r\n Ti.Media.switchCamera(Ti.Media.CAMERA_FRONT);\r\n }\r\n});\r\n{code}\r\n\r\n2. Click 'Switch' button for test.\r\n\r\n*Expected Result:*\r\n\r\nThe front (facing the user, showing their face on the screen) camera should load.\r\n\r\n*Actual Result:*\r\n\r\nThe back camera loads only.\r\n\r\n*Note: It works on 5.3.1.GA version.*\r\n\r\nThanks.", "attachment": [], "flagged": false, "summary": "iOS: Ti.Media.switchCamera() fails to switch camera.", "creator": { "name": "morahman", "key": "morahman", "displayName": "Motiur Rahman", "active": true, "timeZone": "Asia/Dhaka" }, "subtasks": [], "reporter": { "name": "morahman", "key": "morahman", "displayName": "Motiur Rahman", "active": true, "timeZone": "Asia/Dhaka" }, "environment": "Operating System\r\n Name = Mac OS X\r\n Version = 10.11.4\r\n Architecture = 64bit\r\n # CPUs = 4\r\n Memory = 8589934592\r\nNode.js\r\n Node.js Version = 4.5.0\r\n npm Version = 2.15.9\r\nTitanium CLI\r\n CLI Version = 5.0.9\r\nTitanium SDK\r\n SDK Version = 5.5.0.GA\r\n Target Platform = iphone 5s v9.3.4, v10", "closedSprints": [ { "id": 722, "state": "closed", "name": "2016 Sprint 20 SDK", "startDate": "2016-09-28T16:50:17.299Z", "endDate": "2016-10-12T16:50:00.000Z", "completeDate": "2016-10-10T06:17:01.016Z", "originBoardId": 114 } ], "comment": { "comments": [ { "id": "397151", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Note: Similar to TIMOB-17470, the camera can only be switched after the UI is displayed!", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-24T13:14:01.000+0000", "updated": "2016-09-24T13:14:01.000+0000" }, { "id": "397324", "author": { "name": "eric.harms@gmail.com", "key": "eric.harms@gmail.com", "displayName": "eric harms", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Hans --\r\n\r\nIve had something similar in our app prior to 5.5.0.GA and XCode8 -- and it worked. I added a _.delay() to wait for the UI to load, and the camera would switch.\r\n\r\nNow using IOS10 on the device and XCode 8 with Ti 5.5.0.GA, if I use the example above (and same with my app's code) and add the same kind of delay to wait for the UI to be loaded, Ti.Media.switchCamera(Ti.Media.CAMERA_FRONT) does not fire anymore on a device with IOS10.\r\n\r\ni can put other things in the event listener for the switchCamera button click event, and they do fire, so I know the click event is being handled.\r\n\r\nI can alert the current Ti.Media.camera, which comes up as 0 when the camera loads and the UI is ready.\r\n\r\nI updated the sample code of this ticket as follows, the _.delay() of applying the eventListener (to simulate that the UI has completed loading) is at the end.\r\n\r\nI can't get the camera to switch checking the current camera, or by setting it explicitly.\r\n\r\nThanks,\r\nEric\r\n\r\nTI 5.5.0.GA\r\nXCode 8\r\nOSX Sierra 10.12\r\nTI CLI 5.0.9\r\nIPhone 6+ / IOS 10.0.1\r\n\r\n\r\n{code:java}\r\nvar win = Ti.UI.createWindow({\r\n layout: \"vertical\"\r\n});\r\nwin.open();\r\n \r\nvar button = Ti.UI.createButton({\r\n title: \"Camera\",\r\n top: 20,\r\n width: 200,\r\n height: 200\r\n});\r\n \r\nbutton.addEventListener(\"click\", takePics);\r\n \r\nwin.add(button);\r\n \r\nvar view = Ti.UI.createView();\r\n \r\nvar take = Ti.UI.createView({\r\n \r\n bottom: 20,\r\n backgroundColor: \"white\",\r\n width: 70,\r\n height: 70,\r\n borderRadius: 35\r\n \r\n});\r\n \r\nvar switchCamera = Ti.UI.createButton({\r\n \r\n top: 30,\r\n title: \"Switch\",\r\n right: 30,\r\n backgroundColor: \"red\",\r\n width: 50,\r\n height: 50,\r\n borderRadius: 25\r\n \r\n});\r\n \r\n// Add to the parent view.\r\nview.add(take);\r\nview.add(switchCamera);\r\n \r\nfunction takePics() {\r\n Ti.Media.showCamera({\r\n success: function(e) {\r\n Ti.API.info(e.media);\r\n \r\n },\r\n error: function(e) {\r\n alert(e);\r\n },\r\n autohide: false,\r\n overlay: view,\r\n saveToPhotoGallery: true,\r\n mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],\r\n showControls: false,\r\n allowEditing: false\r\n });\r\n \r\n}\r\n \r\ntake.addEventListener('click', function(e) {\r\n Ti.Media.takePicture();\r\n});\r\n\r\n_.delay(function() {\r\n\r\n switchCamera.addEventListener('click', function() {\r\n alert(Ti.Media.camera);\r\n if (Ti.Media.camera == Ti.Media.CAMERA_FRONT) {\r\n Ti.Media.switchCamera(Ti.Media.CAMERA_REAR);\r\n alert('switch to rear camera');\r\n Ti.Media.vibrate();\r\n } else {\r\n Ti.Media.switchCamera(Ti.Media.CAMERA_FRONT);\r\n alert('switch to front camera');\r\n Ti.Media.vibrate();\r\n }\r\n alert('should switch')\r\n\r\n Ti.Media.switchCamera(Ti.Media.CAMERA_FRONT);\r\n Ti.Media.vibrate();\r\n });\r\n});\r\n{code}", "updateAuthor": { "name": "eric.harms@gmail.com", "key": "eric.harms@gmail.com", "displayName": "eric harms", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2016-09-26T22:39:00.000+0000", "updated": "2016-09-26T22:39:00.000+0000" }, { "id": "397414", "author": { "name": "eric.harms@gmail.com", "key": "eric.harms@gmail.com", "displayName": "eric harms", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Hans,\r\n\r\nNevermind my reply here -- I think there might be something else going on.\r\n\r\nThanks", "updateAuthor": { "name": "eric.harms@gmail.com", "key": "eric.harms@gmail.com", "displayName": "eric harms", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2016-09-27T17:26:50.000+0000", "updated": "2016-09-27T17:26:50.000+0000" }, { "id": "397422", "author": { "name": "eric.harms@gmail.com", "key": "eric.harms@gmail.com", "displayName": "eric harms", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Hans,\r\n\r\nFollow up here -- the ability to be able to switch the camera seems to rely on having this property in tiapp.xml\r\n\r\ntrue, value must be true\r\n\r\nI need to ti clean when removing or adding it to see the effect, or the tiapp.xml does not get reset.\r\n\r\nwithout that property in tiapp.xml, Ti.Media.switchCamera(camera) does not seem to work.\r\n\r\nI tried this in my app, which was built before 5.1.0 so it did not have this property (looked like the property was new in 5.1.0.GA -- https://docs.appcelerator.com/platform/release-notes/?version=5.1.0.GA#js_thread). I also tried it with a clean test app using 5.5.0.GA and the code I added above in this thread, removing then adding the property to tiapp.xml, and can confirm it breaks then works as expected.\r\n\r\nthanks\r\nEric", "updateAuthor": { "name": "eric.harms@gmail.com", "key": "eric.harms@gmail.com", "displayName": "eric harms", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2016-09-27T19:27:28.000+0000", "updated": "2016-09-27T19:27:28.000+0000" }, { "id": "397541", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Hey Eric, good catch! I guess I know in which direction we can investigate now. Thanks!", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-28T17:22:17.000+0000", "updated": "2016-09-28T17:22:17.000+0000" }, { "id": "397543", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "[~capsizeno4] Fixed! The issue was that we did not ensure that the code is being executed from the correct thread (UI-thread). I also scanned the rest of the camera-API to ensure it includes the macro as well - it does. \r\n\r\nPR (master): https://github.com/appcelerator/titanium_mobile/pull/8443\r\n\r\n[~cng] Please let me know if we can consider this fix for 6.0.0 as well.\r\n\r\nDemo:\r\n{code:javascript}\r\nvar win = Ti.UI.createWindow({\r\n layout: \"vertical\"\r\n});\r\nwin.open();\r\n\r\nvar button = Ti.UI.createButton({\r\n title: \"Camera\",\r\n top: 20,\r\n width: 200,\r\n height: 200\r\n});\r\n\r\nbutton.addEventListener(\"click\", takePics);\r\n\r\nwin.add(button);\r\n\r\nvar view = Ti.UI.createView();\r\n\r\nvar take = Ti.UI.createView({\r\n bottom: 20,\r\n backgroundColor: \"white\",\r\n width: 70,\r\n height: 70,\r\n borderRadius: 35\r\n});\r\n\r\nvar switchCamera = Ti.UI.createButton({\r\n top: 30,\r\n title: \"Switch\",\r\n right: 30,\r\n backgroundColor: \"red\",\r\n tintColor: \"white\",\r\n width: 60,\r\n height: 60,\r\n borderRadius: 30\r\n});\r\n\r\n// Add to the parent view.\r\nview.add(take);\r\nview.add(switchCamera);\r\n\r\nfunction takePics() {\r\n Ti.Media.showCamera({\r\n success: function(e) {\r\n Ti.API.info(e.media);\r\n\r\n },\r\n error: function(e) {\r\n alert(e);\r\n },\r\n autohide: false,\r\n overlay: view,\r\n mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],\r\n showControls: false\r\n });\r\n\r\n}\r\n\r\ntake.addEventListener('click', function(e) {\r\n Ti.Media.takePicture();\r\n});\r\n\r\n//var value = true;\r\nswitchCamera.addEventListener('click', function() {\r\n Ti.API.info(\"Switch camera!\");\r\n if (Ti.Media.camera == Ti.Media.CAMERA_FRONT) {\r\n Ti.Media.switchCamera(Ti.Media.CAMERA_REAR);\r\n } else {\r\n Ti.Media.switchCamera(Ti.Media.CAMERA_FRONT);\r\n }\r\n});\r\n{code}", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-28T17:29:35.000+0000", "updated": "2016-09-28T17:34:14.000+0000" }, { "id": "397549", "author": { "name": "eric.harms@gmail.com", "key": "eric.harms@gmail.com", "displayName": "eric harms", "active": true, "timeZone": "America/Los_Angeles" }, "body": "excellent Hans nice one\r\n\r\nEric", "updateAuthor": { "name": "eric.harms@gmail.com", "key": "eric.harms@gmail.com", "displayName": "eric harms", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2016-09-28T18:15:54.000+0000", "updated": "2016-09-28T18:15:54.000+0000" }, { "id": "397602", "author": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "body": "This is like a regression so yes we need it for 6.0.0.", "updateAuthor": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-09-29T06:37:55.000+0000", "updated": "2016-09-29T06:37:55.000+0000" }, { "id": "397603", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "PR (6_0_X): https://github.com/appcelerator/titanium_mobile/pull/8447", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-29T06:44:28.000+0000", "updated": "2016-09-29T06:44:28.000+0000" }, { "id": "397606", "author": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "body": "CR and FT passed. PRs merged.", "updateAuthor": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-09-29T06:50:15.000+0000", "updated": "2016-09-29T06:50:15.000+0000" }, { "id": "397660", "author": { "name": "jlongton", "key": "jlongton", "displayName": "Josh Longton", "active": true, "timeZone": "Europe/London" }, "body": "Verified as fixed.\r\n\r\nTested On: \r\n\r\n{noformat}\r\niPhone 5 9.3.5\r\niPhone 6 10.0\r\nMac OSX El Capitan 10.12 \r\nTi SDK: 6.0.0.v20160929031439\r\nAppc Studio: 4.8.0.201609232005 \r\nAppc NPM: 4.2.8-7 \r\nApp CLI: 6.0.0-54 \r\nXcode 8.0 \r\nNode v4.4.7\r\n{noformat}\r\n\r\n*Closing ticket.*", "updateAuthor": { "name": "jlongton", "key": "jlongton", "displayName": "Josh Longton", "active": true, "timeZone": "Europe/London" }, "created": "2016-09-29T17:42:09.000+0000", "updated": "2016-09-29T17:42:09.000+0000" } ], "maxResults": 16, "total": 16, "startAt": 0 } } }