Skip to content

Commit 353b596

Browse files
authored
Implements --manifest-orientation and changes how --orientation works so we can now pass the setting to the SDL orientation hint (#2739)
1 parent 5376a93 commit 353b596

File tree

7 files changed

+234
-77
lines changed

7 files changed

+234
-77
lines changed

doc/source/buildoptions.rst

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,17 @@ options (this list may not be exhaustive):
5757
- ``--package``: The Java package name for your project. e.g. ``org.example.yourapp``.
5858
- ``--name``: The app name.
5959
- ``--version``: The version number.
60-
- ``--orientation``: Usually one of ``portait``, ``landscape``,
61-
``sensor`` to automatically rotate according to the device
62-
orientation, or ``user`` to do the same but obeying the user's
63-
settings. The full list of valid options is given under
64-
``android:screenOrientation`` in the `Android documentation
65-
<https://developer.android.com/guide/topics/manifest/activity-element.html>`__.
60+
- ``--orientation``: The orientations that the app will display in.
61+
(Available options are ``portrait``, ``landscape``, ``portrait-reverse``, ``landscape-reverse``).
62+
Since Android ignores ``android:screenOrientation`` when in multi-window mode
63+
(Which is the default on Android 12+), this option will also set the window orientation hints
64+
for the SDL bootstrap. If multiple orientations are given,
65+
``android:screenOrientation`` will be set to ``unspecified``.
66+
- ``--manifest-orientation``: The orientation that will be set for the ``android:screenOrientation``
67+
attribute of the activity in the ``AndroidManifest.xml`` file. If not set, the value
68+
will be synthesized from the ``--orientation`` option.
69+
The full list of valid options is given under ``android:screenOrientation``
70+
in the `Android documentation <https://developer.android.com/guide/topics/manifest/activity-element.html>`__.
6671
- ``--icon``: A path to the png file to use as the application icon.
6772
- ``--permission``: A permission that needs to be declared into the App ``AndroidManifest.xml``.
6873
For multiple permissions, add multiple ``--permission`` arguments.
@@ -136,12 +141,16 @@ ready.
136141
- ``--package``: The Java package name for your project. e.g. ``org.example.yourapp``.
137142
- ``--name``: The app name.
138143
- ``--version``: The version number.
139-
- ``--orientation``: Usually one of ``portait``, ``landscape``,
140-
``sensor`` to automatically rotate according to the device
141-
orientation, or ``user`` to do the same but obeying the user's
142-
settings. The full list of valid options is given under
143-
``android:screenOrientation`` in the `Android documentation
144-
<https://developer.android.com/guide/topics/manifest/activity-element.html>`__.
144+
- ``--orientation``: The orientations that the app will display in.
145+
(Available options are ``portrait``, ``landscape``, ``portrait-reverse``, ``landscape-reverse``).
146+
Since Android ignores ``android:screenOrientation`` when in multi-window mode
147+
(Which is the default on Android 12+), this setting is not guaranteed to work, and
148+
you should consider to implement a custom orientation change handler in your app.
149+
- ``--manifest-orientation``: The orientation that will be set in the ``android:screenOrientation``
150+
attribute of the activity in the ``AndroidManifest.xml`` file. If not set, the value
151+
will be synthesized from the ``--orientation`` option.
152+
The full list of valid options is given under ``android:screenOrientation``
153+
in the `Android documentation <https://developer.android.com/guide/topics/manifest/activity-element.html>`__.
145154
- ``--icon``: A path to the png file to use as the application icon.
146155
- ``--permission``: A permission name for the app,
147156
e.g. ``--permission VIBRATE``. For multiple permissions, add

pythonforandroid/bdistapk.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ def finalize_options(self):
4343
if option == 'permissions':
4444
for perm in value:
4545
sys.argv.append('--permission={}'.format(perm))
46+
elif option == 'orientation':
47+
for orient in value:
48+
sys.argv.append('--orientation={}'.format(orient))
4649
elif value in (None, 'None'):
4750
sys.argv.append('--{}'.format(option))
4851
else:

pythonforandroid/bootstraps/common/build/build.py

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,8 @@ def make_package(args):
249249
with open(os.path.join(env_vars_tarpath, "p4a_env_vars.txt"), "w") as f:
250250
if hasattr(args, "window"):
251251
f.write("P4A_IS_WINDOWED=" + str(args.window) + "\n")
252-
if hasattr(args, "orientation"):
253-
f.write("P4A_ORIENTATION=" + str(args.orientation) + "\n")
252+
if hasattr(args, "sdl_orientation_hint"):
253+
f.write("KIVY_ORIENTATION=" + str(args.sdl_orientation_hint) + "\n")
254254
f.write("P4A_NUMERIC_VERSION=" + str(args.numeric_version) + "\n")
255255
f.write("P4A_MINSDK=" + str(args.min_sdk_version) + "\n")
256256

@@ -690,20 +690,54 @@ def _decode_advanced_permission(permission):
690690
return _permissions
691691

692692

693-
def parse_args_and_make_package(args=None):
694-
global BLACKLIST_PATTERNS, WHITELIST_PATTERNS, PYTHON
693+
def get_sdl_orientation_hint(orientations):
694+
SDL_ORIENTATION_MAP = {
695+
"landscape": "LandscapeLeft",
696+
"portrait": "Portrait",
697+
"portrait-reverse": "PortraitUpsideDown",
698+
"landscape-reverse": "LandscapeRight",
699+
}
700+
return " ".join(
701+
[SDL_ORIENTATION_MAP[x] for x in orientations if x in SDL_ORIENTATION_MAP]
702+
)
703+
695704

705+
def get_manifest_orientation(orientations, manifest_orientation=None):
706+
# If the user has specifically set an orientation to use in the manifest,
707+
# use that.
708+
if manifest_orientation is not None:
709+
return manifest_orientation
710+
711+
# If multiple or no orientations are specified, use unspecified in the manifest,
712+
# as we can only specify one orientation in the manifest.
713+
if len(orientations) != 1:
714+
return "unspecified"
715+
716+
# Convert the orientation to a value that can be used in the manifest.
717+
# If the specified orientation is not supported, use unspecified.
718+
MANIFEST_ORIENTATION_MAP = {
719+
"landscape": "landscape",
720+
"portrait": "portrait",
721+
"portrait-reverse": "reversePortrait",
722+
"landscape-reverse": "reverseLandscape",
723+
}
724+
return MANIFEST_ORIENTATION_MAP.get(orientations[0], "unspecified")
725+
726+
727+
def get_dist_ndk_min_api_level():
696728
# Get the default minsdk, equal to the NDK API that this dist is built against
697729
try:
698730
with open('dist_info.json', 'r') as fileh:
699731
info = json.load(fileh)
700-
default_min_api = int(info['ndk_api'])
701-
ndk_api = default_min_api
732+
ndk_api = int(info['ndk_api'])
702733
except (OSError, KeyError, ValueError, TypeError):
703734
print('WARNING: Failed to read ndk_api from dist info, defaulting to 12')
704-
default_min_api = 12 # The old default before ndk_api was introduced
705-
ndk_api = 12
735+
ndk_api = 12 # The old default before ndk_api was introduced
736+
return ndk_api
706737

738+
739+
def create_argument_parser():
740+
ndk_api = get_dist_ndk_min_api_level()
707741
import argparse
708742
ap = argparse.ArgumentParser(description='''\
709743
Package a Python application for Android (using
@@ -786,19 +820,21 @@ def parse_args_and_make_package(args=None):
786820
ap.add_argument('--window', dest='window', action='store_true',
787821
default=False,
788822
help='Indicate if the application will be windowed')
823+
ap.add_argument('--manifest-orientation', dest='manifest_orientation',
824+
help=('The orientation that will be set in the '
825+
'android:screenOrientation attribute of the activity '
826+
'in the AndroidManifest.xml file. If not set, '
827+
'the value will be synthesized from the --orientation option.'))
789828
ap.add_argument('--orientation', dest='orientation',
790-
default='portrait',
791-
help=('The orientation that the game will '
792-
'display in. '
793-
'Usually one of "landscape", "portrait", '
794-
'"sensor", or "user" (the same as "sensor" '
795-
'but obeying the '
796-
'user\'s Android rotation setting). '
797-
'The full list of options is given under '
798-
'android_screenOrientation at '
799-
'https://developer.android.com/guide/'
800-
'topics/manifest/'
801-
'activity-element.html'))
829+
action="append", default=[],
830+
choices=['portrait', 'landscape', 'landscape-reverse', 'portrait-reverse'],
831+
help=('The orientations that the app will display in. '
832+
'Since Android ignores android:screenOrientation '
833+
'when in multi-window mode (Which is the default on Android 12+), '
834+
'this option will also set the window orientation hints '
835+
'for apps using the (default) SDL bootstrap.'
836+
'If multiple orientations are given, android:screenOrientation '
837+
'will be set to "unspecified"'))
802838

803839
ap.add_argument('--enable-androidx', dest='enable_androidx',
804840
action='store_true',
@@ -853,9 +889,9 @@ def parse_args_and_make_package(args=None):
853889
ap.add_argument('--sdk', dest='sdk_version', default=-1,
854890
type=int, help=('Deprecated argument, does nothing'))
855891
ap.add_argument('--minsdk', dest='min_sdk_version',
856-
default=default_min_api, type=int,
892+
default=ndk_api, type=int,
857893
help=('Minimum Android SDK version that the app supports. '
858-
'Defaults to {}.'.format(default_min_api)))
894+
'Defaults to {}.'.format(ndk_api)))
859895
ap.add_argument('--allow-minsdk-ndkapi-mismatch', default=False,
860896
action='store_true',
861897
help=('Allow the --minsdk argument to be different from '
@@ -918,6 +954,15 @@ def parse_args_and_make_package(args=None):
918954
ap.add_argument('--activity-class-name', dest='activity_class_name', default=DEFAULT_PYTHON_ACTIVITY_JAVA_CLASS,
919955
help='The full java class name of the main activity')
920956

957+
return ap
958+
959+
960+
def parse_args_and_make_package(args=None):
961+
global BLACKLIST_PATTERNS, WHITELIST_PATTERNS, PYTHON
962+
963+
ndk_api = get_dist_ndk_min_api_level()
964+
ap = create_argument_parser()
965+
921966
# Put together arguments, and add those from .p4a config file:
922967
if args is None:
923968
args = sys.argv[1:]
@@ -964,6 +1009,13 @@ def _read_configuration():
9641009

9651010
args.permissions = parse_permissions(args.permissions)
9661011

1012+
args.manifest_orientation = get_manifest_orientation(
1013+
args.orientation, args.manifest_orientation
1014+
)
1015+
1016+
if get_bootstrap_name() == "sdl2":
1017+
args.sdl_orientation_hint = get_sdl_orientation_hint(args.orientation)
1018+
9671019
if args.res_xmls and isinstance(args.res_xmls[0], list):
9681020
args.res_xmls = [x for res in args.res_xmls for x in res]
9691021

pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
<activity android:name="{{args.android_entrypoint}}"
7070
android:label="@string/app_name"
7171
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale|uiMode{% if args.min_sdk_version >= 8 %}|uiMode{% endif %}{% if args.min_sdk_version >= 13 %}|screenSize|smallestScreenSize{% endif %}{% if args.min_sdk_version >= 17 %}|layoutDirection{% endif %}{% if args.min_sdk_version >= 24 %}|density{% endif %}"
72-
android:screenOrientation="{{ args.orientation }}"
72+
android:screenOrientation="{{ args.manifest_orientation }}"
7373
android:exported="true"
7474
{% if args.activity_launch_mode %}
7575
android:launchMode="{{ args.activity_launch_mode }}"

pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<activity android:name="org.kivy.android.PythonActivity"
6262
android:label="@string/app_name"
6363
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale|uiMode{% if args.min_sdk_version >= 8 %}|uiMode{% endif %}{% if args.min_sdk_version >= 13 %}|screenSize|smallestScreenSize{% endif %}{% if args.min_sdk_version >= 17 %}|layoutDirection{% endif %}{% if args.min_sdk_version >= 24 %}|density{% endif %}"
64-
android:screenOrientation="{{ args.orientation }}"
64+
android:screenOrientation="{{ args.manifest_orientation }}"
6565
android:exported="true"
6666
{% if args.activity_launch_mode %}
6767
android:launchMode="{{ args.activity_launch_mode }}"

testapps/on_device_unit_tests/setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
'arch': 'armeabi-v7a',
4949
'bootstrap' : 'sdl2',
5050
'permissions': ['INTERNET', 'VIBRATE'],
51-
'orientation': 'sensor',
51+
'orientation': ['portrait', 'landscape'],
5252
'service': 'P4a_test_service:app_service.py',
5353
},
5454
'aab':
@@ -62,7 +62,7 @@
6262
'arch': 'armeabi-v7a',
6363
'bootstrap' : 'sdl2',
6464
'permissions': ['INTERNET', 'VIBRATE'],
65-
'orientation': 'sensor',
65+
'orientation': ['portrait', 'landscape'],
6666
'service': 'P4a_test_service:app_service.py',
6767
},
6868
'aar':

0 commit comments

Comments
 (0)