mirror of
https://github.com/SK-la/osu-framework.git
synced 2026-03-13 11:20:31 +00:00
Full NRT pass on Android
Includes everything except `AndroidInputHandler`s as those will be covered separately.
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using Android.App;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Android;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
@@ -11,7 +9,7 @@ using Android.Runtime;
|
||||
using Android.Views;
|
||||
using ManagedBass;
|
||||
using osu.Framework.Bindables;
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
|
||||
namespace osu.Framework.Android
|
||||
{
|
||||
@@ -43,22 +41,17 @@ namespace osu.Framework.Android
|
||||
/// </summary>
|
||||
public SystemUiFlags UIVisibilityFlags
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(Window != null);
|
||||
return (SystemUiFlags)Window.DecorView.SystemUiVisibility;
|
||||
}
|
||||
get => (SystemUiFlags)Window.AsNonNull().DecorView.SystemUiVisibility;
|
||||
set
|
||||
{
|
||||
Debug.Assert(Window != null);
|
||||
systemUiFlags = value;
|
||||
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)value;
|
||||
Window.AsNonNull().DecorView.SystemUiVisibility = (StatusBarVisibility)value;
|
||||
}
|
||||
}
|
||||
|
||||
private SystemUiFlags systemUiFlags;
|
||||
|
||||
private AndroidGameView gameView;
|
||||
private AndroidGameView gameView = null!;
|
||||
|
||||
public override void OnTrimMemory([GeneratedEnum] TrimMemory level)
|
||||
{
|
||||
@@ -66,7 +59,7 @@ namespace osu.Framework.Android
|
||||
gameView.Host?.Collect();
|
||||
}
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
protected override void OnCreate(Bundle? savedInstanceState)
|
||||
{
|
||||
// The default current directory on android is '/'.
|
||||
// On some devices '/' maps to the app data directory. On others it maps to the root of the internal storage.
|
||||
@@ -79,11 +72,9 @@ namespace osu.Framework.Android
|
||||
|
||||
UIVisibilityFlags = SystemUiFlags.LayoutFlags | SystemUiFlags.ImmersiveSticky | SystemUiFlags.HideNavigation | SystemUiFlags.Fullscreen;
|
||||
|
||||
Debug.Assert(Window != null);
|
||||
|
||||
// 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
|
||||
// This sets back the UI flags to hidden once the interaction with the on-screen keyboard has finished.
|
||||
Window.DecorView.SystemUiVisibilityChange += (_, e) =>
|
||||
Window.AsNonNull().DecorView.SystemUiVisibilityChange += (_, e) =>
|
||||
{
|
||||
if ((SystemUiFlags)e.Visibility != systemUiFlags)
|
||||
{
|
||||
@@ -93,8 +84,7 @@ namespace osu.Framework.Android
|
||||
|
||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
||||
{
|
||||
Debug.Assert(Window.Attributes != null);
|
||||
Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
||||
Window.AsNonNull().Attributes.AsNonNull().LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
||||
}
|
||||
|
||||
gameView.HostStarted += host =>
|
||||
@@ -104,9 +94,9 @@ namespace osu.Framework.Android
|
||||
RunOnUiThread(() =>
|
||||
{
|
||||
if (!allow.NewValue)
|
||||
Window.AddFlags(WindowManagerFlags.KeepScreenOn);
|
||||
Window?.AddFlags(WindowManagerFlags.KeepScreenOn);
|
||||
else
|
||||
Window.ClearFlags(WindowManagerFlags.KeepScreenOn);
|
||||
Window?.ClearFlags(WindowManagerFlags.KeepScreenOn);
|
||||
});
|
||||
}, true);
|
||||
};
|
||||
@@ -141,17 +131,17 @@ namespace osu.Framework.Android
|
||||
// On some devices and keyboard combinations the OnKeyDown event does not propagate the key event to the view.
|
||||
// Here it is done manually to ensure that the keys actually land in the view.
|
||||
|
||||
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent e)
|
||||
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent? e)
|
||||
{
|
||||
return gameView.OnKeyDown(keyCode, e);
|
||||
}
|
||||
|
||||
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent e)
|
||||
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent? e)
|
||||
{
|
||||
return gameView.OnKeyUp(keyCode, e);
|
||||
}
|
||||
|
||||
public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent e)
|
||||
public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent? e)
|
||||
{
|
||||
return gameView.OnKeyLongPress(keyCode, e);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Android.App;
|
||||
@@ -11,6 +9,7 @@ using osu.Framework.Android.Graphics.Textures;
|
||||
using osu.Framework.Android.Graphics.Video;
|
||||
using osu.Framework.Android.Input;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics.Video;
|
||||
using osu.Framework.Input;
|
||||
@@ -65,7 +64,7 @@ namespace osu.Framework.Android
|
||||
public override IEnumerable<string> UserStoragePaths => new[]
|
||||
{
|
||||
// not null as internal "external storage" is always available.
|
||||
Application.Context.GetExternalFilesDir(string.Empty)!.ToString(),
|
||||
Application.Context.GetExternalFilesDir(string.Empty).AsNonNull().ToString(),
|
||||
};
|
||||
|
||||
public override bool OpenFileExternally(string filename) => false;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using Android.Content;
|
||||
using Android.Graphics;
|
||||
@@ -15,19 +13,19 @@ using Android.Views.InputMethods;
|
||||
using osu.Framework.Android.Input;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Platform;
|
||||
using osuTK.Graphics;
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
|
||||
namespace osu.Framework.Android
|
||||
{
|
||||
public class AndroidGameView : osuTK.Android.AndroidGameView
|
||||
{
|
||||
public AndroidGameHost Host { get; private set; }
|
||||
public AndroidGameHost? Host { get; private set; }
|
||||
|
||||
public AndroidGameActivity Activity { get; }
|
||||
public AndroidGameActivity Activity { get; } = null!;
|
||||
|
||||
public BindableSafeArea SafeAreaPadding { get; } = new BindableSafeArea();
|
||||
|
||||
@@ -62,9 +60,9 @@ namespace osu.Framework.Android
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Game game;
|
||||
private readonly Game game = null!;
|
||||
|
||||
private InputMethodManager inputMethodManager;
|
||||
private InputMethodManager? inputMethodManager;
|
||||
|
||||
/// <summary>
|
||||
/// Whether <see cref="AndroidTextInput"/> is active.
|
||||
@@ -128,8 +126,10 @@ namespace osu.Framework.Android
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent e)
|
||||
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent? e)
|
||||
{
|
||||
if (e == null) return base.OnKeyDown(keyCode, e);
|
||||
|
||||
switch (keyCode)
|
||||
{
|
||||
// Do not consume Volume keys, so the system can handle them
|
||||
@@ -151,14 +151,18 @@ namespace osu.Framework.Android
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent e)
|
||||
public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent? e)
|
||||
{
|
||||
if (e == null) return base.OnKeyLongPress(keyCode, e);
|
||||
|
||||
KeyLongPress?.Invoke(keyCode, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent e)
|
||||
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent? e)
|
||||
{
|
||||
if (e == null) return base.OnKeyUp(keyCode, e);
|
||||
|
||||
KeyUp?.Invoke(keyCode, e);
|
||||
return true;
|
||||
}
|
||||
@@ -206,12 +210,10 @@ namespace osu.Framework.Android
|
||||
/// </summary>
|
||||
private void updateSafeArea()
|
||||
{
|
||||
Debug.Assert(Display != null);
|
||||
|
||||
// compute the usable screen area.
|
||||
|
||||
var screenSize = new Point();
|
||||
Display.GetRealSize(screenSize);
|
||||
Display.AsNonNull().GetRealSize(screenSize);
|
||||
var screenArea = new RectangleI(0, 0, screenSize.X, screenSize.Y);
|
||||
var usableScreenArea = screenArea;
|
||||
|
||||
@@ -257,8 +259,10 @@ namespace osu.Framework.Android
|
||||
public override bool OnCheckIsTextEditor() => textInputActive;
|
||||
|
||||
/// <returns><c>null</c> to disable input methods</returns>
|
||||
public override IInputConnection OnCreateInputConnection(EditorInfo outAttrs)
|
||||
public override IInputConnection? OnCreateInputConnection(EditorInfo? outAttrs)
|
||||
{
|
||||
if (outAttrs == null) throw new ArgumentNullException(nameof(outAttrs));
|
||||
|
||||
// Properly disable native input methods so that the software keyboard doesn't unexpectedly open.
|
||||
// Eg. when pressing keys on a hardware keyboard.
|
||||
if (!textInputActive)
|
||||
@@ -274,7 +278,7 @@ namespace osu.Framework.Android
|
||||
textInputActive = true;
|
||||
Activity.RunOnUiThread(() =>
|
||||
{
|
||||
inputMethodManager.RestartInput(this); // this syncs the Android input method state with `OnCreateInputConnection()`.
|
||||
inputMethodManager?.RestartInput(this); // this syncs the Android input method state with `OnCreateInputConnection()`.
|
||||
RequestFocus();
|
||||
inputMethodManager?.ShowSoftInput(this, 0);
|
||||
});
|
||||
@@ -285,7 +289,7 @@ namespace osu.Framework.Android
|
||||
textInputActive = false;
|
||||
Activity.RunOnUiThread(() =>
|
||||
{
|
||||
inputMethodManager.RestartInput(this);
|
||||
inputMethodManager?.RestartInput(this);
|
||||
inputMethodManager?.HideSoftInputFromWindow(WindowToken, HideSoftInputFlags.None);
|
||||
ClearFocus();
|
||||
});
|
||||
@@ -316,27 +320,27 @@ namespace osu.Framework.Android
|
||||
/// <summary>
|
||||
/// Invoked on a key down event.
|
||||
/// </summary>
|
||||
public new event Action<Keycode, KeyEvent> KeyDown;
|
||||
public new event Action<Keycode, KeyEvent>? KeyDown;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked on a key up event.
|
||||
/// </summary>
|
||||
public new event Action<Keycode, KeyEvent> KeyUp;
|
||||
public new event Action<Keycode, KeyEvent>? KeyUp;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked on a key long press event.
|
||||
/// </summary>
|
||||
public event Action<Keycode, KeyEvent> KeyLongPress;
|
||||
public event Action<Keycode, KeyEvent>? KeyLongPress;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when text is committed by an <see cref="AndroidInputConnection"/>.
|
||||
/// </summary>
|
||||
public event Action<string> CommitText;
|
||||
public event Action<string>? CommitText;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the <see cref="game"/> has been started on the <see cref="Host"/>.
|
||||
/// </summary>
|
||||
public event Action<AndroidGameHost> HostStarted;
|
||||
public event Action<AndroidGameHost>? HostStarted;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Bindables;
|
||||
@@ -29,7 +27,7 @@ namespace osu.Framework.Android
|
||||
set { }
|
||||
}
|
||||
|
||||
public event Action CursorStateChanged;
|
||||
public event Action? CursorStateChanged;
|
||||
|
||||
public override CursorState CursorState
|
||||
{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Framework.Platform;
|
||||
|
||||
namespace osu.Framework.Android
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Android.Graphics;
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Android.Runtime;
|
||||
using FFmpeg.AutoGen;
|
||||
using osu.Framework.Extensions.EnumExtensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics.Video;
|
||||
using osu.Framework.Logging;
|
||||
|
||||
@@ -151,11 +149,9 @@ namespace osu.Framework.Android.Graphics.Video
|
||||
const string java_vm_field_name = "java_vm";
|
||||
|
||||
var jvmPtrInfo = typeof(JNIEnv).GetField(java_vm_field_name, BindingFlags.NonPublic | BindingFlags.Static);
|
||||
object jvmPtrObj = jvmPtrInfo?.GetValue(null);
|
||||
object? jvmPtrObj = jvmPtrInfo?.GetValue(null);
|
||||
|
||||
Debug.Assert(jvmPtrObj != null);
|
||||
|
||||
int result = av_jni_set_java_vm((void*)(IntPtr)jvmPtrObj, null);
|
||||
int result = av_jni_set_java_vm((void*)(IntPtr)jvmPtrObj.AsNonNull(), null);
|
||||
if (result < 0)
|
||||
throw new InvalidOperationException($"Couldn't pass Java VM handle to FFmpeg: ${result}");
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using Android.Views;
|
||||
using Android.Views.InputMethods;
|
||||
using Java.Lang;
|
||||
@@ -11,40 +9,43 @@ namespace osu.Framework.Android.Input
|
||||
{
|
||||
internal class AndroidInputConnection : BaseInputConnection
|
||||
{
|
||||
public AndroidGameView TargetView { get; set; }
|
||||
private readonly AndroidGameView targetView;
|
||||
|
||||
public AndroidInputConnection(AndroidGameView targetView, bool fullEditor)
|
||||
: base(targetView, fullEditor)
|
||||
{
|
||||
TargetView = targetView;
|
||||
this.targetView = targetView;
|
||||
}
|
||||
|
||||
public override bool CommitText(ICharSequence text, int newCursorPosition)
|
||||
public override bool CommitText(ICharSequence? text, int newCursorPosition)
|
||||
{
|
||||
if (text.Length() != 0)
|
||||
if (text?.Length() > 0)
|
||||
{
|
||||
TargetView.OnCommitText(text.ToString());
|
||||
targetView.OnCommitText(text.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.CommitText(text, newCursorPosition);
|
||||
}
|
||||
|
||||
public override bool SendKeyEvent(KeyEvent e)
|
||||
public override bool SendKeyEvent(KeyEvent? e)
|
||||
{
|
||||
if (e == null)
|
||||
return base.SendKeyEvent(e);
|
||||
|
||||
switch (e.Action)
|
||||
{
|
||||
case KeyEventActions.Down:
|
||||
TargetView?.OnKeyDown(e.KeyCode, e);
|
||||
targetView.OnKeyDown(e.KeyCode, e);
|
||||
return true;
|
||||
|
||||
case KeyEventActions.Up:
|
||||
TargetView?.OnKeyUp(e.KeyCode, e);
|
||||
targetView.OnKeyUp(e.KeyCode, e);
|
||||
return true;
|
||||
|
||||
case KeyEventActions.Multiple:
|
||||
TargetView?.OnKeyDown(e.KeyCode, e);
|
||||
TargetView?.OnKeyUp(e.KeyCode, e);
|
||||
targetView.OnKeyDown(e.KeyCode, e);
|
||||
targetView.OnKeyUp(e.KeyCode, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.Views;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using Android;
|
||||
using Android.App;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using Android.App;
|
||||
using osu.Framework.Android;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user