Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-18956] Android orientation change detection is missing reverse orientation distinction

GitHub Issuen/a
TypeBug
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2015-06-11T21:06:36.000+0000
Affected Version/sn/a
Fix Version/sRelease 4.1.0
ComponentsAndroid
Labelsandroid, orientationChange
ReporterJohn V Pataki
AssigneeAshraf Abu
Created2015-05-26T21:21:58.000+0000
Updated2017-03-21T23:51:54.000+0000

Description

The documentation confirms that this is missing from the various places where in Android you could detect orientation change. * Ti.Gesture.orientationchange event http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Gesture-event-orientationchange * Ti.Gesture.orientation property http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Gesture-property-orientation * Ti.Android.Activity. requestedOrientation property http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Android.Activity-property-requestedOrientation From docs: On Android and Mobile Web, returns the orientation of the current window, and *never reports the "reverse" orientations* (LANDSCAPE_RIGHT and UPSIDE_PORTRAIT). Android itself does report the reverse orientation changes, Titanium is just not surfacing this level of reporting. This deficiency prevents being able to detect precisely to which orientation has the device been rotated to with respect to a view, such as a camera view needed for barcode scanning. When the device has rotated but the view (and the object which is the subject of the scanning) has not rotated, you must be able to determine what the relative rotation is without the possibility of being 180 degrees off. Let me try to illustrate how this becomes a problem with some ASCII art and the scenario being a barcode scanning camera view in a module where the app must report to the module the orientation change. This is just an example of 1 use case where this deficiency can be seen as a problem. Let's say this is your device in portrait orientation: {noformat} A---B |a-b| || || |c-d| C---D {noformat} ABCD are the corners of the hardware, abcd are the corners of the camera view. Let's say the camera sensor is mounted such that the top-left corner of the picture is nearest to the A corner, the top-right corner of the picture is nearest to the B corner, etc. In this case, the rotation difference between the camera sensor and the camera view is 0 degrees, so the pixel at the top-left corner of the picture can go near the 'a' corner of the view, the pixel at the top-right corner of the picture can go near the 'b' corner of the view, etc. If the activity supports landscape-right orientation, then this is how your screen will look like if you rotate your device 90 degrees counter-clockwise: {noformat} B------C |a----b| || || |c----d| A------D {noformat} The important thing to realize is that the camera sensor rotated with the hardware but the view didn't, and neither did the object you are pointing the camera at. So the top-left pixel is still near the A corner as far as the camera sensor is concerned, but now that pixel needs to go to the 'c' corner of the view, otherwise from your (the user's) perspective the camera feed will look like it's rotated 90 degrees clockwise (because the object in front of the camera didn't rotate with the camera sensor). This can be achieved by the app telling the module that the activity's UI is now in landscape-right orientation, which the module will interpret not as landscape-right per se, rather as "rotate the camera feed 90 degrees counter-clockwise". I think by now it should be clear why we need to distinguish between landscape-right and landscape-left, but just for completeness -- if the activity supports landscape-left orientation as well, then this is how your screen will look like if you rotate your device 90 degrees clockwise (relative to portrait): {noformat} C------A |a----b| || || |c----d| D------B {noformat} The top-left pixel is still near the A corner as far as the camera sensor is concerned, but now that pixel needs to go to the 'b' corner of the view. In this case the module would have to rotate the camera feed clockwise by 90 degrees. If we can't distinguish between these two cases (i.e. landscape-left and landscape-right), then the best we can do is to rotate the camera feed by 90 degrees in the same direction in both cases, which will mean that the camera feed will appear off by 180-degrees (i.e. upside-down) to the user in one of those cases. Similar logic applies to portrait vs. reversePortrait. A work around would be to recreate orientation change handling in the module, however the better solution should be to improve this handling in the Titanium SDK so that the app can notify the module using Titanium SDK available functions/events about this change instead of the module needing to unnecessarily replicate Titanium SDK capabilities just to improve them. This works as expected in the iOS Titanium SDK.

Comments

  1. Rick Blalock 2015-05-26

    [~rtlechuga] - FYI this is needed to complete the new ti.barcode module
  2. Scott Davenport 2015-05-28

    [~ingo] how can we get this scoped and in? Amerisource has been waiting for the new barcode module and this is a blocker issue.
  3. Ingo Muschenetz 2015-05-28

    I'm not sure why this wasn't just created in TIMOB. Anyway, we'll review it.
  4. Ingo Muschenetz 2015-05-28

    [~cng] please schedule this for an upcoming sprint.
  5. Ashraf Abu 2015-06-08

    [~patakijv] [~rblalock] Hi, I'm working on this and just want to check on some things. Currently, on an Android tablet, when I rotate an application, I can get it to display on Landscape_right, landscape_left, portrait and portrait_reverse. On an Android phone, an application can generally rotate Landscape_right, landscape_left and portrait. The app, in a phone won't rotate portrait_reverse. In this scenario, would you still need the phone to produce an event i.e. output "portrait_reverse" when it is upside down even though app is still right side up? In android tablet, where the app can rotate to portrait_reverse, getting it to produce "portrait_reverse" is no problem as the app does rotate. If there is no event needed for portrait_reverse when the application itself doesn't rotate portrait_reverse, the code change can be pretty straight forward.
  6. Ashraf Abu 2015-06-09

    PR: https://github.com/appcelerator/titanium_mobile/pull/6899 Please test using an Android table and an Android phone to see the difference. I was testing with a Nexus 9 and Nexus 6. In Nexus 6, the app would not rotate upside down, hence UPSIDE_PORTRAIT is not available. App.js
       var win = Titanium.UI.createWindow({  
           title:'Window',
           backgroundColor:'#fff'
       });
       
       win.orientationModes = [ 
           Titanium.UI.PORTRAIT, 
           Titanium.UI.UPSIDE_PORTRAIT,
           Titanium.UI.LANDSCAPE_LEFT,
       	Titanium.UI.LANDSCAPE_RIGHT
       ];
       
       Ti.Gesture.addEventListener('orientationchange', function(e){
           switch(e.orientation) {
           case Ti.UI.LANDSCAPE_RIGHT:
               Ti.API.info("LANDSCAPE_RIGHT");
       		Ti.UI.createNotification({
       	    	message:"LANDSCAPE_RIGHT",
       	    	duration: Ti.UI.NOTIFICATION_DURATION_SHORT
       		}).show();
               break;
           case Ti.UI.LANDSCAPE_LEFT:
               Ti.API.info("LANDSCAPE_LEFT");
       		Ti.UI.createNotification({
       	    	message:"LANDSCAPE_LEFT",
       	    	duration: Ti.UI.NOTIFICATION_DURATION_SHORT
       		}).show();
               break;
           case Ti.UI.UPSIDE_PORTRAIT:
               Ti.API.info("UPSIDE_PORTRAIT");
       		Ti.UI.createNotification({
       	    	message:"UPSIDE_PORTRAIT",
       	    	duration: Ti.UI.NOTIFICATION_DURATION_SHORT
       		}).show();
               break;
           case Ti.UI.PORTRAIT:
               Ti.API.info("PORTRAIT");
       		Ti.UI.createNotification({
       	    	message:"PORTRAIT",
       	    	duration: Ti.UI.NOTIFICATION_DURATION_SHORT
       		}).show();
               break;
           default:
               Ti.API.info("Unknown!!");
       	} 
       });
       
       win.open();
       
  7. Lee Morris 2017-03-21

    Closing ticket as fixed.

JSON Source