mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Re-structured the low-level Android native code
Please see the forum post "Re-structuring of JUCE’s low-level Android code" and the BREAKING-CHANGES.txt for more information.
This commit is contained in:
parent
463f5ea5b0
commit
008b7a9ab2
75 changed files with 7812 additions and 7376 deletions
|
|
@ -116,7 +116,7 @@ public:
|
|||
#elif JUCE_ANDROID
|
||||
|
||||
#define JUCE_CREATE_APPLICATION_DEFINE(AppClass) \
|
||||
juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); }
|
||||
extern "C" juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); }
|
||||
|
||||
#define JUCE_MAIN_FUNCTION_DEFINITION
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace Android
|
|||
|
||||
struct Handler
|
||||
{
|
||||
Handler() : nativeHandler (getEnv()->NewObject (AndroidHandler, AndroidHandler.constructor)) {}
|
||||
Handler() : nativeHandler (LocalRef<jobject> (getEnv()->NewObject (AndroidHandler, AndroidHandler.constructor))) {}
|
||||
~Handler() { clearSingletonInstance(); }
|
||||
|
||||
JUCE_DECLARE_SINGLETON (Handler, false)
|
||||
|
|
@ -72,7 +72,7 @@ struct AndroidMessageQueue : private Android::Runnable
|
|||
JUCE_DECLARE_SINGLETON_SINGLETHREADED (AndroidMessageQueue, true)
|
||||
|
||||
AndroidMessageQueue()
|
||||
: self (CreateJavaInterface (this, "java/lang/Runnable").get())
|
||||
: self (CreateJavaInterface (this, "java/lang/Runnable"))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +131,7 @@ bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* cons
|
|||
{
|
||||
return AndroidMessageQueue::getInstance()->post (message);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MessageManager::broadcastMessage (const String&)
|
||||
{
|
||||
|
|
@ -149,18 +150,26 @@ void MessageManager::stopDispatchLoop()
|
|||
void messageCallback() override
|
||||
{
|
||||
auto* env = getEnv();
|
||||
LocalRef<jobject> activity (getCurrentActivity());
|
||||
|
||||
jmethodID quitMethod = env->GetMethodID (JuceAppActivity, "finishAndRemoveTask", "()V");
|
||||
|
||||
if (quitMethod != 0)
|
||||
if (activity != nullptr)
|
||||
{
|
||||
env->CallVoidMethod (android.activity, quitMethod);
|
||||
return;
|
||||
}
|
||||
jmethodID quitMethod = env->GetMethodID (AndroidActivity, "finishAndRemoveTask", "()V");
|
||||
|
||||
quitMethod = env->GetMethodID (JuceAppActivity, "finish", "()V");
|
||||
jassert (quitMethod != 0);
|
||||
env->CallVoidMethod (android.activity, quitMethod);
|
||||
if (quitMethod != 0)
|
||||
{
|
||||
env->CallVoidMethod (activity.get(), quitMethod);
|
||||
return;
|
||||
}
|
||||
|
||||
quitMethod = env->GetMethodID (AndroidActivity, "finish", "()V");
|
||||
jassert (quitMethod != 0);
|
||||
env->CallVoidMethod (activity.get(), quitMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -168,4 +177,134 @@ void MessageManager::stopDispatchLoop()
|
|||
quitMessagePosted = true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class JuceAppLifecycle : public ActivityLifecycleCallbacks
|
||||
{
|
||||
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()
|
||||
{
|
||||
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
|
||||
{
|
||||
checkCreated();
|
||||
}
|
||||
|
||||
void onActivityDestroyed (jobject activity) override
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
// if the main activity is being destroyed, only then tear-down JUCE
|
||||
if (env->IsSameObject (getMainActivity().get(), activity) != 0)
|
||||
{
|
||||
JUCEApplicationBase::appWillTerminateByForce();
|
||||
JNIClassBase::releaseAllClasses (env);
|
||||
|
||||
jclass systemClass = (jclass) env->FindClass ("java/lang/System");
|
||||
jmethodID exitMethod = env->GetStaticMethodID (systemClass, "exit", "(I)V");
|
||||
env->CallStaticVoidMethod (systemClass, exitMethod, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void onActivityStarted (jobject) override
|
||||
{
|
||||
checkCreated();
|
||||
}
|
||||
|
||||
void onActivityPaused (jobject) override
|
||||
{
|
||||
if (auto* app = JUCEApplicationBase::getInstance())
|
||||
app->suspended();
|
||||
}
|
||||
|
||||
void onActivityResumed (jobject) override
|
||||
{
|
||||
checkInitialised();
|
||||
|
||||
if (auto* app = JUCEApplicationBase::getInstance())
|
||||
app->resumed();
|
||||
}
|
||||
|
||||
static JuceAppLifecycle& getInstance (juce::JUCEApplicationBase* (*initSymbolAddr)())
|
||||
{
|
||||
static JuceAppLifecycle juceAppLifecycle (initSymbolAddr);
|
||||
return juceAppLifecycle;
|
||||
}
|
||||
|
||||
private:
|
||||
void checkCreated()
|
||||
{
|
||||
if (JUCEApplicationBase::getInstance() == nullptr)
|
||||
{
|
||||
DBG (SystemStats::getJUCEVersion());
|
||||
|
||||
JUCEApplicationBase::createInstance = createApplicationSymbol;
|
||||
|
||||
initialiseJuce_GUI();
|
||||
|
||||
if (! JUCEApplicationBase::createInstance())
|
||||
jassertfalse; // you must supply an application object for an android app!
|
||||
|
||||
jassert (MessageManager::getInstance()->isThisTheMessageThread());
|
||||
}
|
||||
}
|
||||
|
||||
void checkInitialised()
|
||||
{
|
||||
checkCreated();
|
||||
|
||||
if (! hasBeenInitialised)
|
||||
{
|
||||
if (auto* app = JUCEApplicationBase::getInstance())
|
||||
{
|
||||
hasBeenInitialised = app->initialiseApp();
|
||||
|
||||
if (! hasBeenInitialised)
|
||||
exit (app->shutdownApp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GlobalRef myself;
|
||||
juce::JUCEApplicationBase* (*createApplicationSymbol)();
|
||||
bool hasBeenInitialised = false;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
File juce_getExecutableFile();
|
||||
|
||||
void juce_juceEventsAndroidStartApp()
|
||||
{
|
||||
auto dllPath = juce_getExecutableFile().getFullPathName();
|
||||
auto addr = reinterpret_cast<juce::JUCEApplicationBase*(*)()> (DynamicLibrary (dllPath)
|
||||
.getFunction ("juce_CreateApplication"));
|
||||
|
||||
if (addr != nullptr)
|
||||
JuceAppLifecycle::getInstance (addr);
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue