Android Question Change orientation lock based on device?

Scotter

Active Member
Licensed User
So... I locked orientation to portrait because people using my app on phones kept accidentally resetting the activity by rotating the phone. That worked great. UNTIL someone with a FireTV said it looked distorted.

So is the solution for me to change
B4X:
#SupportedOrientations: portrait
to
B4X:
#SupportedOrientations: unspecified
, detect at activity start the device's ?native? orientation (All FireTVs are 16x9 aspect ratio), and then lock orientation to either portrait or landscape, depending on that device's aspect ratio?

If so, how do I programmatically detect device default aspect ratio and then lock orientation to that?

I've already set up a new 640x360 (16x9) variant in the designer.

Thanks!
 

Scotter

Active Member
Licensed User
Search GetDeviceLayoutValues
for more details see Here ....
Another option is separate Activities See this post ...
Thanks! I looked at the thread you referred me to.
No need for reflection or phone library, you can set each activity orientation using the manifest editor, let say you have 2 activities, Main and Extra:
B4X:
SetActivityAttribute(Main, android:screenOrientation, "portrait")
SetActivityAttribute(Extra, android:screenOrientation, "landscape")
I really like this solution because it doesn't require a library be added to my project.
I'm newb enough that I'm not sure how to use this with what I'm doing.
I do know how to use the manifest editor.
What I don't have a deep enough understanding of is how the "main" activity and "extra" activity can be set up in my code. Right now my code has the default "Activity_Create" sub only. Is that the type of "activity" you mean when talking here about SetActivityAttribute(Main/Extra, android:screenOrientation... ?
My situation: I locked orientation to portrait because people using my app on phones kept accidentally resetting the activity by rotating the phone. That worked great and I want to keep it locked for phones. BUT someone with a FireTV and said it looked distorted. So I'd like to force landscape when a device (like FireTV) has a ?native? aspect ratio of 16x8 or 16x9 or whatever. Basically W/H. I don't even need/want to do it for tablets, as people can easily turn those portrait. I've already set up a new 640x360 (16x9) variant in the designer. I posted about the issue earlier in this thread: https://www.b4x.com/android/forum/threads/change-orientation-lock-based-on-device.100992/
Thanks!
I'll start researching the following
B4X:
Sub Process_Globals
    Dim p As Phone
End Sub

If GetDeviceLayoutValues.Width > GetDeviceLayoutValues.Height Then
        p.SetScreenOrientation(0)    'landscape
    Else
        p.SetScreenOrientation(1)    'portrait
    End If
 

Scotter

Active Member
Licensed User
The code above seems straightforward enough to start playing with.
The only question is: should I put the
B4X:
If GetDeviceLayoutValues.Width.... then p.SetScreenOrientation...
into the Activity_Create sub or somewhere else?
Thanks!
 

mangojack

Well-Known Member
Licensed User
Yes .. Activity_Create ... or a separate sub that is called early from Activity_Create.

What I don't have a deep enough understanding of is how the "main" activity and "extra" activity can be set up in my code
The 2 options would be

1 Activity Test device size then ..
B4X:
If GetDeviceLayoutValues.Width > GetDeviceLayoutValues.Height Then
        p.SetScreenOrientation(0)    'landscape
        Activity.LoadLayout("big_tablet")
    Else
        p.SetScreenOrientation(1)    'portrait
        Activity.LoadLayout("small_phone")
    End If

2 (or) 3 Activities - using the manifest approach ..

SetActivityAttribute(SmallActivity, android:screenOrientation, "portrait")
SetActivityAttribute(LargeActivity, android:screenOrientation, "landscape")


In Main Activity ... Test device size then ..
B4X:
If GetDeviceLayoutValues.Width > GetDeviceLayoutValues.Height Then
        StartActivity(LargeActivity)
    Else
        StartActivity(SmallActivity)
    End If

But I'm sure this method would result in a mass of duplicated code ...


Cheers
 
Last edited:

Harris

Expert
Licensed User
This is the way I handle it (for years now). Similar to above. Method placed in a shared code module.

I call SetOro in each resume of every activity.

The assumption is that any screen size less than 6 (change if you want) is a phone - otherwise it is a tablet.
Another assumption is that phones will always be used in portrait mode (most reasonable) and tablets will be used in landscape mode (most practical). For my apps, this is the rule that I enforce. Took me quite some time to figure out the evils of device rotation - but now I know better.

The return boolean value let's me determine what size of device is in use - and I adjust text size accordingly (larger text size on tablets).
I also use lv.scale to determine device density (DPI) to adjust text size....

For example, in real world use, one of my apps runs on tablets, affixed to vehicles, locked into a powered cradle - in a landscape position.
All activities need to be shown in landscape mode - all the time.
Without this method, due to vibration or tilt/slant of vehicle, the mode would sometimes flip to portrait.
Locking the orientation on every (many) activity fixed this issue.

B4X:
' Code module...
' Subs in this code module will be accessible from all modules.

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Public oro As Phone
    Public lv As LayoutValues

End Sub


Sub SetOro As Boolean

    lv = GetDeviceLayoutValues 
    Dim ret As Boolean = False
    Log(" Screen Size: "&lv.ApproximateScreenSize) 
    If lv.ApproximateScreenSize < 6 Then
        oro.SetScreenOrientation( 1 )  ' port
    Else
        oro.SetScreenOrientation( 0 )  ' land
        ret = True
    End If
    Return ret

End Sub
 
Last edited:
Top