A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using Android.App;
5using Android.Content;
6using Android.OS;
7using Android.Runtime;
8using Android.Views;
9using Process = System.Diagnostics.Process;
10
11namespace osu.Framework.Android
12{
13 public abstract class AndroidGameActivity : Activity
14 {
15 protected abstract Game CreateGame();
16
17 /// <summary>
18 /// The visibility flags for the system UI (status and navigation bars)
19 /// </summary>
20 public SystemUiFlags UIVisibilityFlags
21 {
22 get => (SystemUiFlags)Window.DecorView.SystemUiVisibility;
23 set
24 {
25 systemUiFlags = value;
26 Window.DecorView.SystemUiVisibility = (StatusBarVisibility)value;
27 }
28 }
29
30 private SystemUiFlags systemUiFlags;
31
32 private AndroidGameView gameView;
33
34 public override void OnTrimMemory([GeneratedEnum] TrimMemory level)
35 {
36 base.OnTrimMemory(level);
37 gameView.Host?.Collect();
38 }
39
40 protected override void OnCreate(Bundle savedInstanceState)
41 {
42 base.OnCreate(savedInstanceState);
43
44 SetContentView(gameView = new AndroidGameView(this, CreateGame()));
45
46 UIVisibilityFlags = SystemUiFlags.LayoutFlags | SystemUiFlags.ImmersiveSticky | SystemUiFlags.HideNavigation;
47
48 // Firing up the on-screen keyboard (eg: interacting with textboxes) may cause the UI visibility flags to be altered thus showing the navigation bar and potentially the status bar
49 // This sets back the UI flags to hidden once the interaction with the on-screen keyboard has finished.
50 Window.DecorView.SystemUiVisibilityChange += (_, e) =>
51 {
52 if ((SystemUiFlags)e.Visibility != systemUiFlags)
53 {
54 UIVisibilityFlags = systemUiFlags;
55 }
56 };
57
58 if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
59 Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
60
61 gameView.HostStarted += host =>
62 {
63 host.AllowScreenSuspension.Result.BindValueChanged(allow =>
64 {
65 RunOnUiThread(() =>
66 {
67 if (!allow.NewValue)
68 Window.AddFlags(WindowManagerFlags.KeepScreenOn);
69 else
70 Window.ClearFlags(WindowManagerFlags.KeepScreenOn);
71 });
72 }, true);
73 };
74 }
75
76 protected override void OnPause()
77 {
78 base.OnPause();
79 // Because Android is not playing nice with Background - we just kill it
80 Process.GetCurrentProcess().Kill();
81 }
82
83 public override void OnBackPressed()
84 {
85 // Avoid the default implementation that does close the app.
86 // This only happens when the back button could not be captured from OnKeyDown.
87 }
88
89 // On some devices and keyboard combinations the OnKeyDown event does not propagate the key event to the view.
90 // Here it is done manually to ensure that the keys actually land in the view.
91
92 public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent e)
93 {
94 return gameView.OnKeyDown(keyCode, e);
95 }
96
97 public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent e)
98 {
99 return gameView.OnKeyUp(keyCode, e);
100 }
101
102 public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent e)
103 {
104 return gameView.OnKeyLongPress(keyCode, e);
105 }
106 }
107}