mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
Android: Refactor lifecycle callbacks to reduce repetition in lifecycle listener registration
This commit is contained in:
parent
11752d061f
commit
1c2eb2d056
7 changed files with 56 additions and 137 deletions
|
|
@ -429,7 +429,22 @@ void juce_dispatchDelete (JNIEnv*, jobject /*object*/, jlong host)
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
jobject ActivityLifecycleCallbacks::invoke (jobject proxy, jobject method, jobjectArray args)
|
||||
ActivityLifecycleCallbackForwarder::ActivityLifecycleCallbackForwarder (GlobalRef ctx, ActivityLifecycleCallbacks* cb)
|
||||
: appContext (ctx),
|
||||
myself (CreateJavaInterface (this, "android/app/Application$ActivityLifecycleCallbacks")),
|
||||
callbacks (cb)
|
||||
{
|
||||
if (appContext != nullptr && myself != nullptr)
|
||||
getEnv()->CallVoidMethod (appContext, AndroidApplication.registerActivityLifecycleCallbacks, myself.get());
|
||||
}
|
||||
|
||||
ActivityLifecycleCallbackForwarder::~ActivityLifecycleCallbackForwarder()
|
||||
{
|
||||
if (appContext != nullptr && myself != nullptr)
|
||||
getEnv()->CallVoidMethod (appContext, AndroidApplication.unregisterActivityLifecycleCallbacks, myself.get());
|
||||
}
|
||||
|
||||
jobject ActivityLifecycleCallbackForwarder::invoke (jobject proxy, jobject method, jobjectArray args)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
|
|
@ -475,7 +490,7 @@ jobject ActivityLifecycleCallbacks::invoke (jobject proxy, jobject method, jobje
|
|||
|
||||
const auto activity = env->GetArrayLength (args) > 0 ? env->GetObjectArrayElement (args, 0) : (jobject) nullptr;
|
||||
const auto bundle = env->GetArrayLength (args) > 1 ? env->GetObjectArrayElement (args, 1) : (jobject) nullptr;
|
||||
(iter->second) (*this, activity, bundle);
|
||||
(iter->second) (*callbacks, activity, bundle);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1016,9 +1016,11 @@ LocalRef<jobject> CreateJavaInterface (AndroidInterfaceImplementer* implementer,
|
|||
const String& interfaceName);
|
||||
|
||||
//==============================================================================
|
||||
class ActivityLifecycleCallbacks : public AndroidInterfaceImplementer
|
||||
class ActivityLifecycleCallbacks
|
||||
{
|
||||
public:
|
||||
virtual ~ActivityLifecycleCallbacks() = default;
|
||||
|
||||
virtual void onActivityPreCreated (jobject /*activity*/, jobject /*bundle*/) {}
|
||||
virtual void onActivityPreDestroyed (jobject /*activity*/) {}
|
||||
virtual void onActivityPrePaused (jobject /*activity*/) {}
|
||||
|
|
@ -1044,15 +1046,27 @@ public:
|
|||
virtual void onActivityPostStopped (jobject /*activity*/) {}
|
||||
|
||||
virtual void onActivityConfigurationChanged (jobject /*activity*/) {}
|
||||
};
|
||||
|
||||
class ActivityLifecycleCallbackForwarder : private AndroidInterfaceImplementer
|
||||
{
|
||||
public:
|
||||
ActivityLifecycleCallbackForwarder (GlobalRef appContext, ActivityLifecycleCallbacks* callbacks);
|
||||
|
||||
~ActivityLifecycleCallbackForwarder() override;
|
||||
|
||||
private:
|
||||
jobject invoke (jobject, jobject, jobjectArray) override;
|
||||
|
||||
GlobalRef appContext;
|
||||
GlobalRef myself;
|
||||
ActivityLifecycleCallbacks* callbacks = nullptr;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct SurfaceHolderCallback : AndroidInterfaceImplementer
|
||||
struct SurfaceHolderCallback : public AndroidInterfaceImplementer
|
||||
{
|
||||
virtual ~SurfaceHolderCallback() override = default;
|
||||
~SurfaceHolderCallback() override = default;
|
||||
|
||||
virtual void surfaceChanged (LocalRef<jobject> holder, int format, int width, int height) = 0;
|
||||
virtual void surfaceCreated (LocalRef<jobject> holder) = 0;
|
||||
|
|
|
|||
|
|
@ -111,33 +111,9 @@ class JuceActivityWatcher final : public ActivityLifecycleCallbacks
|
|||
public:
|
||||
JuceActivityWatcher()
|
||||
{
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
|
||||
if (appContext != nullptr)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
myself = GlobalRef (CreateJavaInterface (this, "android/app/Application$ActivityLifecycleCallbacks"));
|
||||
env->CallVoidMethod (appContext.get(), AndroidApplication.registerActivityLifecycleCallbacks, myself.get());
|
||||
}
|
||||
|
||||
checkActivityIsMain (androidApkContext);
|
||||
}
|
||||
|
||||
~JuceActivityWatcher() override
|
||||
{
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
|
||||
if (appContext != nullptr && myself != nullptr)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
env->CallVoidMethod (appContext.get(), AndroidApplication.unregisterActivityLifecycleCallbacks, myself.get());
|
||||
clear();
|
||||
myself.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void onActivityStarted (jobject activity) override
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
|
@ -273,10 +249,10 @@ private:
|
|||
return mainActivityClassPath;
|
||||
}
|
||||
|
||||
GlobalRef myself;
|
||||
CriticalSection currentActivityLock;
|
||||
jweak currentActivity = nullptr;
|
||||
jweak mainActivity = nullptr;
|
||||
ActivityLifecycleCallbackForwarder forwarder { GlobalRef { getAppContext() }, this };
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -183,29 +183,6 @@ public:
|
|||
JuceAppLifecycle (juce::JUCEApplicationBase* (*initSymbolAddr)())
|
||||
: createApplicationSymbol (initSymbolAddr)
|
||||
{
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
|
||||
if (appContext != nullptr)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
myself = GlobalRef (CreateJavaInterface (this, "android/app/Application$ActivityLifecycleCallbacks"));
|
||||
env->CallVoidMethod (appContext.get(), AndroidApplication.registerActivityLifecycleCallbacks, myself.get());
|
||||
}
|
||||
}
|
||||
|
||||
~JuceAppLifecycle() override
|
||||
{
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
|
||||
if (appContext != nullptr && myself != nullptr)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
clear();
|
||||
env->CallVoidMethod (appContext.get(), AndroidApplication.unregisterActivityLifecycleCallbacks, myself.get());
|
||||
myself.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void onActivityCreated (jobject, jobject) override
|
||||
|
|
@ -292,6 +269,7 @@ private:
|
|||
GlobalRef myself;
|
||||
juce::JUCEApplicationBase* (*createApplicationSymbol)();
|
||||
bool hasBeenInitialised = false;
|
||||
ActivityLifecycleCallbackForwarder forwarder { GlobalRef { getAppContext() }, this };
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -1308,7 +1308,8 @@ static constexpr int translateAndroidKeyboardFlags (int javaFlags) noexcept
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
class AndroidComponentPeer final : public ComponentPeer
|
||||
class AndroidComponentPeer final : public ComponentPeer,
|
||||
private ActivityLifecycleCallbacks
|
||||
{
|
||||
public:
|
||||
AndroidComponentPeer (Component& comp, int windowStyleFlags, void* nativeViewHandle)
|
||||
|
|
@ -2097,20 +2098,12 @@ public:
|
|||
{
|
||||
void onActivityStarted (jobject /*activity*/) override
|
||||
{
|
||||
auto* env = getEnv();
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
forceDisplayUpdate();
|
||||
|
||||
if (appContext.get() != nullptr)
|
||||
{
|
||||
env->CallVoidMethod (appContext.get(),
|
||||
AndroidApplication.unregisterActivityLifecycleCallbacks,
|
||||
activityCallbackListener.get());
|
||||
clear();
|
||||
activityCallbackListener.clear();
|
||||
|
||||
forceDisplayUpdate();
|
||||
}
|
||||
AndroidComponentPeer::startupActivityCallbackListener.reset();
|
||||
}
|
||||
|
||||
ActivityLifecycleCallbackForwarder forwarder { GlobalRef { getAppContext() }, this };
|
||||
};
|
||||
|
||||
class MainActivityWindowLayoutListener : public AndroidInterfaceImplementer
|
||||
|
|
@ -2530,7 +2523,7 @@ private:
|
|||
//==============================================================================
|
||||
friend class Displays;
|
||||
inline static AndroidComponentPeer* frontWindow = nullptr;
|
||||
inline static GlobalRef activityCallbackListener;
|
||||
inline static std::optional<StartupActivityCallbackListener> startupActivityCallbackListener;
|
||||
|
||||
static constexpr jint GRAVITY_LEFT = 0x3, GRAVITY_TOP = 0x30;
|
||||
static constexpr jint TYPE_APPLICATION = 0x2;
|
||||
|
|
@ -2562,37 +2555,10 @@ bool Desktop::canUseSemiTransparentWindows() noexcept
|
|||
return true;
|
||||
}
|
||||
|
||||
class Desktop::NativeDarkModeChangeDetectorImpl : public ActivityLifecycleCallbacks
|
||||
class Desktop::NativeDarkModeChangeDetectorImpl : private ActivityLifecycleCallbacks
|
||||
{
|
||||
public:
|
||||
NativeDarkModeChangeDetectorImpl()
|
||||
{
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
|
||||
if (appContext != nullptr)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
myself = GlobalRef (CreateJavaInterface (this, "android/app/Application$ActivityLifecycleCallbacks"));
|
||||
env->CallVoidMethod (appContext.get(), AndroidApplication.registerActivityLifecycleCallbacks, myself.get());
|
||||
}
|
||||
}
|
||||
|
||||
~NativeDarkModeChangeDetectorImpl() override
|
||||
{
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
|
||||
if (appContext != nullptr && myself != nullptr)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
env->CallVoidMethod (appContext.get(),
|
||||
AndroidApplication.unregisterActivityLifecycleCallbacks,
|
||||
myself.get());
|
||||
clear();
|
||||
myself.clear();
|
||||
}
|
||||
}
|
||||
NativeDarkModeChangeDetectorImpl() = default;
|
||||
|
||||
bool isDarkModeEnabled() const noexcept { return darkModeEnabled; }
|
||||
|
||||
|
|
@ -2625,8 +2591,8 @@ private:
|
|||
UI_MODE_NIGHT_UNDEFINED = 0x00000000,
|
||||
UI_MODE_NIGHT_YES = 0x00000020;
|
||||
|
||||
GlobalRef myself;
|
||||
bool darkModeEnabled = getDarkModeSetting();
|
||||
ActivityLifecycleCallbackForwarder forwarder { GlobalRef { getAppContext() }, this };
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeDarkModeChangeDetectorImpl)
|
||||
|
|
@ -2972,20 +2938,9 @@ void Displays::findDisplays (float masterScale)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (AndroidComponentPeer::activityCallbackListener == nullptr)
|
||||
else if (! AndroidComponentPeer::startupActivityCallbackListener.has_value())
|
||||
{
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
|
||||
if (appContext.get() != nullptr)
|
||||
{
|
||||
AndroidComponentPeer::activityCallbackListener = GlobalRef (CreateJavaInterface (
|
||||
new AndroidComponentPeer::StartupActivityCallbackListener,
|
||||
"android/app/Application$ActivityLifecycleCallbacks"));
|
||||
|
||||
env->CallVoidMethod (appContext,
|
||||
AndroidApplication.registerActivityLifecycleCallbacks,
|
||||
AndroidComponentPeer::activityCallbackListener.get());
|
||||
}
|
||||
AndroidComponentPeer::startupActivityCallbackListener.emplace();
|
||||
}
|
||||
|
||||
displays.add (d);
|
||||
|
|
|
|||
|
|
@ -490,8 +490,7 @@ private:
|
|||
};
|
||||
|
||||
//==============================================================================
|
||||
struct CameraDevice::Pimpl
|
||||
: private ActivityLifecycleCallbacks
|
||||
struct CameraDevice::Pimpl : private ActivityLifecycleCallbacks
|
||||
{
|
||||
using InternalOpenCameraResultCallback = std::function<void (const String& /*cameraId*/, const String& /*error*/)>;
|
||||
|
||||
|
|
@ -504,7 +503,6 @@ struct CameraDevice::Pimpl
|
|||
maxWidth (maxWidthToUse),
|
||||
maxHeight (maxHeightToUse),
|
||||
cameraId (cameraIdToUse),
|
||||
activityLifeListener (CreateJavaInterface (this, "android/app/Application$ActivityLifecycleCallbacks")),
|
||||
cameraManager (initialiseCameraManager()),
|
||||
cameraCharacteristics (initialiseCameraCharacteristics (cameraManager, cameraId)),
|
||||
streamConfigurationMap (cameraCharacteristics),
|
||||
|
|
@ -516,10 +514,7 @@ struct CameraDevice::Pimpl
|
|||
|
||||
~Pimpl() override
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
env->CallVoidMethod (getAppContext().get(), AndroidApplication.unregisterActivityLifecycleCallbacks, activityLifeListener.get());
|
||||
activityLifeListener.clear();
|
||||
callbackForwarder.reset();
|
||||
}
|
||||
|
||||
JUCE_DECLARE_WEAK_REFERENCEABLE (Pimpl)
|
||||
|
|
@ -551,7 +546,7 @@ struct CameraDevice::Pimpl
|
|||
{
|
||||
if (granted)
|
||||
{
|
||||
getEnv()->CallVoidMethod (getAppContext().get(), AndroidApplication.registerActivityLifecycleCallbacks, activityLifeListener.get());
|
||||
callbackForwarder.emplace (GlobalRef { getAppContext() }, static_cast<ActivityLifecycleCallbacks*> (this));
|
||||
scopedCameraDevice.reset (new ScopedCameraDevice (*this, cameraId, cameraManager, handler, getAutoFocusModeToUse()));
|
||||
}
|
||||
else
|
||||
|
|
@ -2809,7 +2804,7 @@ private:
|
|||
String cameraId;
|
||||
InternalOpenCameraResultCallback cameraOpenCallback;
|
||||
|
||||
GlobalRef activityLifeListener;
|
||||
std::optional<ActivityLifecycleCallbackForwarder> callbackForwarder;
|
||||
|
||||
GlobalRef cameraManager;
|
||||
GlobalRef cameraCharacteristics;
|
||||
|
|
|
|||
|
|
@ -344,8 +344,9 @@ private:
|
|||
};
|
||||
|
||||
//==============================================================================
|
||||
struct VideoComponent::Pimpl
|
||||
: public AndroidViewComponent, private ActivityLifecycleCallbacks, private SurfaceHolderCallback
|
||||
struct VideoComponent::Pimpl : public AndroidViewComponent,
|
||||
private ActivityLifecycleCallbacks,
|
||||
private SurfaceHolderCallback
|
||||
{
|
||||
Pimpl (VideoComponent& ownerToUse, bool)
|
||||
: owner (ownerToUse),
|
||||
|
|
@ -360,14 +361,6 @@ struct VideoComponent::Pimpl
|
|||
|
||||
LocalRef<jobject> appContext (getAppContext());
|
||||
|
||||
if (appContext != nullptr)
|
||||
{
|
||||
ActivityLifecycleCallbacks* callbacks = dynamic_cast<ActivityLifecycleCallbacks*> (this);
|
||||
|
||||
activityLifeListener = GlobalRef (CreateJavaInterface (callbacks, "android/app/Application$ActivityLifecycleCallbacks"));
|
||||
env->CallVoidMethod (appContext.get(), AndroidApplication.registerActivityLifecycleCallbacks, activityLifeListener.get());
|
||||
}
|
||||
|
||||
{
|
||||
LocalRef<jobject> surfaceView (env->NewObject (AndroidSurfaceView, AndroidSurfaceView.constructor, getAppContext().get()));
|
||||
LocalRef<jobject> holder (env->CallObjectMethod (surfaceView.get(), AndroidSurfaceView.getHolder));
|
||||
|
|
@ -397,13 +390,6 @@ struct VideoComponent::Pimpl
|
|||
surfaceHolderCallback.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (activityLifeListener != nullptr)
|
||||
{
|
||||
env->CallVoidMethod (getAppContext().get(), AndroidApplication.unregisterActivityLifecycleCallbacks, activityLifeListener.get());
|
||||
ActivityLifecycleCallbacks::clear();
|
||||
activityLifeListener.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void loadAsync (const URL& url, std::function<void (const URL&, Result)> callback)
|
||||
|
|
@ -1696,7 +1682,7 @@ private:
|
|||
VideoComponent& owner;
|
||||
|
||||
MediaSession mediaSession;
|
||||
GlobalRef activityLifeListener;
|
||||
ActivityLifecycleCallbackForwarder forwarder { GlobalRef { getAppContext() }, this };
|
||||
#if JUCE_SYNC_VIDEO_VOLUME_WITH_OS_MEDIA_VOLUME
|
||||
SystemVolumeListener systemVolumeListener;
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue