Browse Source

Initial working on mic recording support for Android.

--HG--
branch : androidmic
Miku AuahDark 5 years ago
parent
commit
0f23b0e4a0

+ 53 - 0
src/common/android.cpp

@@ -266,6 +266,59 @@ bool hasBackgroundMusic()
 	return result;
 	return result;
 }
 }
 
 
+bool hasRecordingPermission()
+{
+	JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
+	jobject activity = (jobject) SDL_AndroidGetActivity();
+
+	jclass clazz(env->GetObjectClass(activity));
+	jmethodID method_id = env->GetMethodID(clazz, "hasRecordAudioPermission", "()Z");
+	jboolean result = false;
+
+	if (methodID == nullptr)
+		env->ExceptionClear();
+	else
+		result = env->CallBooleanMethod(activity, method_id);
+
+	env->DeleteLocalRef(activity);
+	env->DeleteLocalRef(clazz);
+
+	return result;
+}
+
+
+void showRecordingPermissionMissingDialog()
+{
+	JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
+	jobject activity = (jobject) SDL_AndroidGetActivity();
+	jclass clazz(env->GetObjectClass(activity));
+	jmethodID methodID = env->GetMethodID(clazz, "requestRecordAudioPermission", "()V");
+
+	if (methodID == nullptr)
+		env->ExceptionClear();
+	else
+		env->CallVoidMethod(activity, methodID);
+
+	env->DeleteLocalRef(clazz);
+	env->DeleteLocalRef(activity);
+}
+
+void showRecordingPermissionMissingDialog()
+{
+	JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
+	jobject activity = (jobject) SDL_AndroidGetActivity();
+	jclass clazz(env->GetObjectClass(activity));
+	jmethodID methodID = env->GetMethodID(clazz, "showRecordingAudioPermissionMissingDialog", "()V");
+
+	if (methodID == nullptr)
+		env->ExceptionClear();
+	else
+		env->CallVoidMethod(activity, methodID);
+
+	env->DeleteLocalRef(clazz);
+	env->DeleteLocalRef(activity);
+}
+
 } // android
 } // android
 } // love
 } // love
 
 

+ 6 - 0
src/common/android.h

@@ -74,6 +74,12 @@ bool createStorageDirectories();
 
 
 bool hasBackgroundMusic();
 bool hasBackgroundMusic();
 
 
+bool hasRecordingPermission();
+
+void requestRecordingPermission();
+
+void showRecordingPermissionMissingDialog();
+
 } // android
 } // android
 } // love
 } // love
 
 

+ 39 - 1
src/modules/audio/Audio.cpp

@@ -21,8 +21,10 @@
 #include "Audio.h"
 #include "Audio.h"
 #include "common/config.h"
 #include "common/config.h"
 
 
-#ifdef LOVE_IOS
+#if defined(LOVE_IOS)
 #include "common/ios.h"
 #include "common/ios.h"
+#elif defined(LOVE_ANDROID)
+#include "common/android.h"
 #endif
 #endif
 
 
 namespace love
 namespace love
@@ -30,6 +32,42 @@ namespace love
 namespace audio
 namespace audio
 {
 {
 
 
+static bool requestRecPermission = false;
+
+void setRequestRecordingPermission(bool rec)
+{
+	requestRecPermission = rec;
+}
+
+bool getRequestRecordingPermission()
+{
+	return requestRecPermission;
+}
+
+bool hasRecordingPermission()
+{
+#if defined(LOVE_ANDROID)
+	return love::android::hasRecordingPermission();
+#else
+	// Always available(?)
+	return true;
+#endif
+}
+
+void requestRecordingPermission()
+{
+#ifdef LOVE_ANDROID
+	love::android::requestRecordingPermission();
+#endif
+}
+
+void _showRecordingPermissionMissingDialog()
+{
+#ifdef LOVE_ANDROID
+	love::android::showRecordingPermissionMissingDialog();
+#endif
+}
+
 bool Audio::setMixWithSystem(bool mix)
 bool Audio::setMixWithSystem(bool mix)
 {
 {
 #ifdef LOVE_IOS
 #ifdef LOVE_IOS

+ 28 - 0
src/modules/audio/Audio.h

@@ -45,6 +45,34 @@ class SoundData;
 namespace audio
 namespace audio
 {
 {
 
 
+/*
+ * In some platforms (notably Android), recording from mic
+ * requires user permission. This function sets whetever to
+ * request the permission later or not.
+ */
+void setRequestRecordingPermission(bool rec);
+
+/*
+ * Gets whetever recording permission will be requested.
+ */
+bool getRequestRecordingPermission();
+
+/*
+ * Gets whetever recording permission is granted.
+ */
+bool hasRecordingPermission();
+
+/*
+ * Request recording permission. This is blocking function.
+ */
+void requestRecordingPermission();
+
+/*
+ * In case recording permission is not granted, this
+ * function shows the dialog about the recording permission.
+ */
+void showRecordingPermissionMissingDialog();
+
 /**
 /**
  * The Audio module is responsible for playing back raw sound samples.
  * The Audio module is responsible for playing back raw sound samples.
  **/
  **/

+ 17 - 0
src/modules/audio/openal/Audio.cpp

@@ -101,6 +101,15 @@ Audio::Audio()
 	love::thread::disableSignals();
 	love::thread::disableSignals();
 #endif
 #endif
 
 
+	// Before opening new device, check if recording
+	// is requested.
+	if (getRequestRecordingPermission())
+	{
+		if (!hasRecordingPermission())
+			// Request recording permission on some OSes.
+			requestRecordingPermission();
+	}
+
 	// Passing null for default device.
 	// Passing null for default device.
 	device = alcOpenDevice(nullptr);
 	device = alcOpenDevice(nullptr);
 
 
@@ -399,6 +408,14 @@ void Audio::setDistanceModel(DistanceModel distanceModel)
 
 
 const std::vector<love::audio::RecordingDevice*> &Audio::getRecordingDevices()
 const std::vector<love::audio::RecordingDevice*> &Audio::getRecordingDevices()
 {
 {
+	// If recording permission is not granted, inform user about it
+	// and return empty list.
+	if (!hasRecordingPermission())
+	{
+		showRecordingPermissionMissingDialog();
+		return {};
+	}
+
 	std::vector<std::string> devnames;
 	std::vector<std::string> devnames;
 	std::vector<love::audio::RecordingDevice*> devices;
 	std::vector<love::audio::RecordingDevice*> devices;