1
0
Fork 0
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:
hogliux 2018-11-13 12:33:40 +00:00
parent 463f5ea5b0
commit 008b7a9ab2
75 changed files with 7812 additions and 7376 deletions

View file

@ -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

View file

@ -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