Android: Added sf::getNativeActivity() to retrieve a handle to the current activity

This is only implemented for Android builds and requires the user to include the sub-header specifically. Other platforms will trigger a compiler error, if they try to include this header file.
This commit is contained in:
Mario Liebisch 2015-10-21 11:11:35 +02:00 committed by Lukas Dürrenberger
parent 845c684ec8
commit 9f6f02f988
6 changed files with 210 additions and 15 deletions

View File

@ -2377,3 +2377,21 @@ GENERATE_LEGEND = YES
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# SFML specific aliases
#---------------------------------------------------------------------------
# sfplatform{platform(s)}
# sfplatform{platform(s), header}
#
# Warns the user that some specific class or function is only available on
# specific platforms.
#
# This shouldn't be used for incomplete implementations. It's meant for things
# that will never appear on another platform, e.g. Android's native activity.
#
# If a header is given, the user is informed, that this header must be included
# for the mentioned element to be defined.
ALIASES += sfplatform{1}="<dl class=\"attention\"><dt>Platform Limitation</dt><dd><b>This is only available on \1.</b></dd></dl>"
ALIASES += sfplatform{2}="<dl class=\"attention\"><dt>Platform Limitation</dt><dd><b>This is only available on \1</b> and to use it, you'll have to specifically include \2 in your code.</dd></dl>"

View File

@ -10,6 +10,8 @@
<uses-sdk android:minSdkVersion="9" <uses-sdk android:minSdkVersion="9"
android:targetSdkVersion="19" /> android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.VIBRATE" />
<application android:label="@string/app_name" <application android:label="@string/app_name"
android:icon="@drawable/sfml_logo" android:icon="@drawable/sfml_logo"
android:hasCode="false" android:hasCode="false"

View File

@ -4,7 +4,76 @@
#include <SFML/Audio.hpp> #include <SFML/Audio.hpp>
#include <SFML/Network.hpp> #include <SFML/Network.hpp>
// Do we want to showcase direct JNI/NDK interaction?
// Undefine this to get real cross-platform code.
#define USE_JNI
#if defined(USE_JNI)
// These headers are only needed for direct NDK/JDK interaction
#include <jni.h>
#include <android/native_activity.h>
// Since we want to get the native activity from SFML, we'll have to use an
// extra header here:
#include <SFML/System/NativeActivity.hpp>
// NDK/JNI sub example - call Java code from native code
int vibrate(sf::Time duration)
{
// First we'll need the native activity handle
ANativeActivity *activity = sf::getNativeActivity();
// Retrieve the JVM and JNI environment
JavaVM* vm = activity->vm;
JNIEnv* env = activity->env;
// First, attach this thread to the main thread
JavaVMAttachArgs attachargs;
attachargs.version = JNI_VERSION_1_6;
attachargs.name = "NativeThread";
attachargs.group = NULL;
jint res = vm->AttachCurrentThread(&env, &attachargs);
if (res == JNI_ERR)
return EXIT_FAILURE;
// Retrieve class information
jclass natact = env->FindClass("android/app/NativeActivity");
jclass context = env->FindClass("android/content/Context");
// Get the value of a constant
jfieldID fid = env->GetStaticFieldID(context, "VIBRATOR_SERVICE", "Ljava/lang/String;");
jobject svcstr = env->GetStaticObjectField(context, fid);
// Get the method 'getSystemService' and call it
jmethodID getss = env->GetMethodID(natact, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
jobject vib_obj = env->CallObjectMethod(activity->clazz, getss, svcstr);
// Get the object's class and retrieve the member name
jclass vib_cls = env->GetObjectClass(vib_obj);
jmethodID vibrate = env->GetMethodID(vib_cls, "vibrate", "(J)V");
// Determine the timeframe
jlong length = duration.asMilliseconds();
// Bzzz!
env->CallVoidMethod(vib_obj, vibrate, length);
// Free references
env->DeleteLocalRef(vib_obj);
env->DeleteLocalRef(vib_cls);
env->DeleteLocalRef(svcstr);
env->DeleteLocalRef(context);
env->DeleteLocalRef(natact);
// Detach thread again
vm->DetachCurrentThread();
}
#endif
// This is the actual Android example. You don't have to write any platform
// specific code, unless you want to use things not directly exposed.
// ('vibrate()' in this example; undefine 'USE_JNI' above to disable it)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
sf::RenderWindow window(sf::VideoMode::getDesktopMode(), ""); sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
@ -31,23 +100,26 @@ int main(int argc, char *argv[])
while (window.pollEvent(event)) while (window.pollEvent(event))
{ {
if (event.type == sf::Event::Closed) switch (event.type)
{ {
window.close(); case sf::Event::Closed:
window.close();
break;
case sf::Event::Resized:
view.setSize(event.size.width, event.size.height);
view.setCenter(event.size.width/2, event.size.height/2);
window.setView(view);
break;
case sf::Event::TouchBegan:
if (event.touch.finger == 0)
{
image.setPosition(event.touch.x, event.touch.y);
#if defined(USE_JNI)
vibrate(sf::milliseconds(10));
#endif
}
break;
} }
if (event.type == sf::Event::Resized)
{
view.setSize(event.size.width, event.size.height);
view.setCenter(event.size.width/2, event.size.height/2);
window.setView(view);
}
}
if (sf::Touch::isDown(0))
{
sf::Vector2i position = sf::Touch::getPosition(0);
image.setPosition(position.x, position.y);
} }
window.clear(sf::Color::White); window.clear(sf::Color::White);

View File

@ -0,0 +1,62 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_NATIVEACTIVITY_HPP
#define SFML_NATIVEACTIVITY_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#if !defined(SFML_SYSTEM_ANDROID)
#error NativeActivity.hpp: This header is Android only.
#endif
struct ANativeActivity;
namespace sf
{
////////////////////////////////////////////////////////////
/// \ingroup system
/// \brief Return a pointer to the Android native activity
///
/// You shouldn't have to use this function, unless you want
/// to implement very specific details, that SFML doesn't
/// support, or to use a workaround for a known issue.
///
/// \return Pointer to Android native activity structure
///
/// \sfplatform{Android,SFML/System/NativeActivity.hpp}
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API ANativeActivity* getNativeActivity();
} // namespace sf
#endif // SFML_NATIVEACTIVITY_HPP

View File

@ -0,0 +1,39 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NativeActivity.hpp>
#include <SFML/System/Android/Activity.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
ANativeActivity* getNativeActivity()
{
return priv::getActivity()->activity;
}
} // namespace sf

View File

@ -14,6 +14,7 @@ set(SRC
${INCROOT}/Lock.hpp ${INCROOT}/Lock.hpp
${SRCROOT}/Mutex.cpp ${SRCROOT}/Mutex.cpp
${INCROOT}/Mutex.hpp ${INCROOT}/Mutex.hpp
${INCROOT}/NativeActivity.hpp
${INCROOT}/NonCopyable.hpp ${INCROOT}/NonCopyable.hpp
${SRCROOT}/Sleep.cpp ${SRCROOT}/Sleep.cpp
${INCROOT}/Sleep.hpp ${INCROOT}/Sleep.hpp
@ -75,6 +76,7 @@ else()
set(PLATFORM_SRC ${PLATFORM_SRC} set(PLATFORM_SRC ${PLATFORM_SRC}
${SRCROOT}/Android/Activity.hpp ${SRCROOT}/Android/Activity.hpp
${SRCROOT}/Android/Activity.cpp ${SRCROOT}/Android/Activity.cpp
${SRCROOT}/Android/NativeActivity.cpp
${SRCROOT}/Android/ResourceStream.cpp ${SRCROOT}/Android/ResourceStream.cpp
${SRCROOT}/Android/ResourceStream.cpp ${SRCROOT}/Android/ResourceStream.cpp
) )