This commit is contained in:
Björn Ritzl 2020-07-15 20:24:46 +02:00
parent c61161724a
commit 599f899f07
5 changed files with 77 additions and 103 deletions

View File

@ -22,42 +22,16 @@ import android.view.Surface;
import java.io.IOException; import java.io.IOException;
class AndroidCamera public class AndroidCamera extends Fragment
{ {
private static final String TAG = AndroidCamera.class.getSimpleName(); private static final String TAG = AndroidCamera.class.getSimpleName();
private static final String PERMISSION_FRAGMENT_TAG = PermissionsFragment.class.getSimpleName();
public static class PermissionsFragment extends Fragment {
private AndroidCamera camera;
public PermissionsFragment(final Activity activity, final AndroidCamera camera) {
this.camera = camera;
final FragmentManager fragmentManager = activity.getFragmentManager();
if (fragmentManager.findFragmentByTag(PERMISSION_FRAGMENT_TAG) == null) {
fragmentManager.beginTransaction().add(this, PERMISSION_FRAGMENT_TAG).commit();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult " + requestCode + " " + permissions[0] + " " + grantResults[0]);
camera.onRequestPermissionsResult(grantResults[0]);
}
}
enum CameraMessage enum CameraMessage
{ {
CAMERA_STARTED(0), CAMERA_STARTED(0),
CAMERA_STOPPED(1), CAMERA_STOPPED(1),
CAMERA_NOT_PERMITTED(2), CAMERA_NOT_PERMITTED(2),
CAMERA_ERROR(3), CAMERA_ERROR(3);
CAMERA_SHOW_PERMISSION_RATIONALE(4);
private final int value; private final int value;
@ -70,7 +44,6 @@ class AndroidCamera
} }
} }
private PermissionsFragment permissionFragment;
private Camera camera; private Camera camera;
private SurfaceTexture surface; private SurfaceTexture surface;
private boolean newFrame; private boolean newFrame;
@ -89,42 +62,49 @@ class AndroidCamera
private AndroidCamera(final Context context) private AndroidCamera(final Context context)
{ {
this.context = context; this.context = context;
permissionFragment = new PermissionsFragment((Activity)context, this);
}
private void requestPermission() { final FragmentManager fragmentManager = ((Activity)context).getFragmentManager();
Log.d(TAG, "requestPermission"); if (fragmentManager.findFragmentByTag(TAG) == null) {
final Activity activity = (Activity)context; fragmentManager.beginTransaction().add(this, TAG).commit();
if (Build.VERSION.SDK_INT < 23)
{
Log.d(TAG, "requestPermission SDK_INT < 23");
final int grantResult = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
onRequestPermissionsResult(grantResult);
}
else
{
Log.d(TAG, "requestPermission fragment");
final FragmentManager fragmentManager = activity.getFragmentManager();
final Fragment fragment = fragmentManager.findFragmentByTag(PERMISSION_FRAGMENT_TAG);
final String[] permissions = new String[] { Manifest.permission.CAMERA };
fragment.requestPermissions(permissions, 100);
} }
} }
public synchronized void onRequestPermissionsResult(int grantResult) { @Override
Log.d(TAG, "onRequestPermissionsResult " + grantResult); public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
int grantResult = grantResults[0];
if (grantResult == PackageManager.PERMISSION_GRANTED) if (grantResult == PackageManager.PERMISSION_GRANTED)
{ {
Log.d(TAG, "onRequestPermissionsResult startPreviewAuthorized");
startPreviewAuthorized(); startPreviewAuthorized();
} }
else else
{ {
Log.d(TAG, "onRequestPermissionsResult ERROR");
queueMessage(CameraMessage.CAMERA_ERROR.getValue()); queueMessage(CameraMessage.CAMERA_ERROR.getValue());
} }
} }
private void requestPermission() {
final Activity activity = (Activity)context;
if (Build.VERSION.SDK_INT < 23)
{
final int grantResult = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
// onRequestPermissionsResult(grantResult);
onRequestPermissionsResult(0, new String[] { Manifest.permission.CAMERA }, new int[] { grantResult });
}
else
{
final FragmentManager fragmentManager = activity.getFragmentManager();
final Fragment fragment = fragmentManager.findFragmentByTag(TAG);
final String[] permissions = new String[] { Manifest.permission.CAMERA };
fragment.requestPermissions(permissions, 100);
}
}
private void startPreviewAuthorized() private void startPreviewAuthorized()
{ {
CameraInfo info = new CameraInfo(); CameraInfo info = new CameraInfo();
@ -182,14 +162,13 @@ class AndroidCamera
catch(IOException ioe) catch(IOException ioe)
{ {
} }
Log.d(TAG, "startPreviewAuthorized starting camera");
camera.startPreview(); camera.startPreview();
queueMessage(CameraMessage.CAMERA_STARTED.getValue()); queueMessage(CameraMessage.CAMERA_STARTED.getValue());
} }
public void startPreview() public void startPreview()
{ {
Log.d(TAG, "startPreview");
if(camera != null) if(camera != null)
{ {
queueMessage(CameraMessage.CAMERA_STARTED.getValue()); queueMessage(CameraMessage.CAMERA_STARTED.getValue());

View File

@ -61,7 +61,6 @@ static void Camera_ProcessQueue()
if (message == CAMERA_STARTED) if (message == CAMERA_STARTED)
{ {
dmLogInfo("Camera_ProcessQueue CAMERA_STARTED");
// Increase ref count // Increase ref count
dmScript::LuaHBuffer luabuffer = {g_DefoldCamera.m_VideoBuffer, false}; dmScript::LuaHBuffer luabuffer = {g_DefoldCamera.m_VideoBuffer, false};
dmScript::PushBuffer(L, luabuffer); dmScript::PushBuffer(L, luabuffer);
@ -69,14 +68,9 @@ static void Camera_ProcessQueue()
} }
else if (message == CAMERA_STOPPED) else if (message == CAMERA_STOPPED)
{ {
dmLogInfo("Camera_ProcessQueue CAMERA_STOPPED");
dmScript::Unref(L, LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef); // We want it destroyed by the GC dmScript::Unref(L, LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef); // We want it destroyed by the GC
g_DefoldCamera.m_VideoBufferLuaRef = 0; g_DefoldCamera.m_VideoBufferLuaRef = 0;
} }
else
{
dmLogInfo("Camera_ProcessQueue SOMETHING ELSE");
}
lua_pushnumber(L, (lua_Number)message); lua_pushnumber(L, (lua_Number)message);
int ret = lua_pcall(L, 2, 0, 0); int ret = lua_pcall(L, 2, 0, 0);

View File

@ -8,12 +8,10 @@ static const uint32_t CAMERA_WIDTH = 640;
static const uint32_t CAMERA_HEIGHT = 480; static const uint32_t CAMERA_HEIGHT = 480;
static jclass g_cameraClass = 0; static jclass g_cameraClass = 0;
static jmethodID g_initMethodId = 0; static jobject g_cameraObject = 0;
static jmethodID g_getCameraMethodId = 0;
static jmethodID g_startPreviewMethodId = 0; static jmethodID g_startPreviewMethodId = 0;
static jmethodID g_stopPreviewMethodId = 0; static jmethodID g_stopPreviewMethodId = 0;
static jmethodID g_getCameraMethodId = 0;
static jmethodID g_setCallbackDataMethodId = 0;
static jobject g_cameraObject = 0;
static jint g_data[CAMERA_WIDTH * CAMERA_HEIGHT]; static jint g_data[CAMERA_WIDTH * CAMERA_HEIGHT];
static bool g_frameLock = false; static bool g_frameLock = false;
@ -21,7 +19,6 @@ static bool g_frameLock = false;
static dmBuffer::HBuffer g_VideoBuffer = 0; static dmBuffer::HBuffer g_VideoBuffer = 0;
static JNIEnv* Attach() static JNIEnv* Attach()
{ {
JNIEnv* env; JNIEnv* env;
@ -71,7 +68,6 @@ JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_frameUpdate(
JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_queueMessage(JNIEnv * env, jobject jobj, jint message) JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_queueMessage(JNIEnv * env, jobject jobj, jint message)
{ {
dmLogInfo("Java_com_defold_android_camera_AndroidCamera_queueMessage %d", (int)message);
Camera_QueueMessage((CameraMessage)message); Camera_QueueMessage((CameraMessage)message);
} }
@ -85,45 +81,47 @@ int CameraPlatform_Initialize()
} }
// get the AndroidCamera class // get the AndroidCamera class
jclass tmp = GetClass(env, "com.defold.android.camera/AndroidCamera");
g_cameraClass = (jclass)env->NewGlobalRef(tmp);
if(!g_cameraClass) if(!g_cameraClass)
{ {
jclass tmp = GetClass(env, "com.defold.android.camera/AndroidCamera"); dmLogError("Could not find class 'com.defold.android.camera/AndroidCamera'.");
g_cameraClass = (jclass)env->NewGlobalRef(tmp); Detach(env);
if(!g_cameraClass) return false;
{
dmLogError("Could not find class 'com.defold.android.camera/AndroidCamera'.");
Detach(env);
return false;
}
} }
// get an instance of the AndroidCamera class using the getCamera() method // get an instance of the AndroidCamera class using the getCamera() method
g_getCameraMethodId = env->GetStaticMethodID(g_cameraClass, "getCamera", "(Landroid/content/Context;)Lcom/defold/android/camera/AndroidCamera;");
if(!g_getCameraMethodId) if(!g_getCameraMethodId)
{ {
g_getCameraMethodId = env->GetStaticMethodID(g_cameraClass, "getCamera", "(Landroid/content/Context;)Lcom/defold/android/camera/AndroidCamera;"); dmLogError("Could not get static method 'getCamera'.");
if(!g_getCameraMethodId) Detach(env);
{ return false;
dmLogError("Could not get static method 'getCamera'.");
Detach(env);
return false;
}
} }
jobject tmp1 = env->CallStaticObjectMethod(g_cameraClass, g_getCameraMethodId, dmGraphics::GetNativeAndroidActivity());
g_cameraObject = (jobject)env->NewGlobalRef(tmp1);
if(!g_cameraObject) if(!g_cameraObject)
{ {
jobject tmp1 = env->CallStaticObjectMethod(g_cameraClass, g_getCameraMethodId, dmGraphics::GetNativeAndroidActivity()); dmLogError("Could not create instance.");
g_cameraObject = (jobject)env->NewGlobalRef(tmp1); Detach(env);
return false;
} }
// get reference to startPreview() and stopPreview() methods // get reference to startPreview() and stopPreview() methods
g_startPreviewMethodId = env->GetMethodID(g_cameraClass, "startPreview", "()V");
if(!g_startPreviewMethodId) if(!g_startPreviewMethodId)
{ {
g_startPreviewMethodId = env->GetMethodID(g_cameraClass, "startPreview", "()V"); dmLogError("Could not get startPreview() method.");
assert(g_startPreviewMethodId); Detach(env);
return false;
} }
g_stopPreviewMethodId = env->GetMethodID(g_cameraClass, "stopPreview", "()V");
if(!g_stopPreviewMethodId) if(!g_stopPreviewMethodId)
{ {
g_stopPreviewMethodId = env->GetMethodID(g_cameraClass, "stopPreview", "()V"); dmLogError("Could not get stopPreview() method.");
assert(g_stopPreviewMethodId); Detach(env);
return false;
} }
Detach(env); Detach(env);
@ -132,7 +130,12 @@ int CameraPlatform_Initialize()
void CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams) void CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams)
{ {
dmLogInfo("CameraPlatform_StartCapture"); if (!g_cameraObject)
{
Camera_QueueMessage(CAMERA_ERROR);
return;
}
outparams.m_Width = (uint32_t)CAMERA_WIDTH; outparams.m_Width = (uint32_t)CAMERA_WIDTH;
outparams.m_Height = (uint32_t)CAMERA_HEIGHT; outparams.m_Height = (uint32_t)CAMERA_HEIGHT;
@ -151,23 +154,22 @@ void CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, Cap
g_VideoBuffer = *buffer; g_VideoBuffer = *buffer;
if (g_cameraObject) JNIEnv* env = Attach();
{ env->CallVoidMethod(g_cameraObject, g_startPreviewMethodId);
dmLogInfo("CameraPlatform_StartCapture JNI"); Detach(env);
JNIEnv* env = Attach();
env->CallVoidMethod(g_cameraObject, g_startPreviewMethodId);
Detach(env);
}
} }
void CameraPlatform_StopCapture() void CameraPlatform_StopCapture()
{ {
if (g_cameraObject) if (!g_cameraObject)
{ {
JNIEnv* env = Attach(); Camera_QueueMessage(CAMERA_ERROR);
env->CallVoidMethod(g_cameraObject, g_stopPreviewMethodId); return;
Detach(env);
} }
JNIEnv* env = Attach();
env->CallVoidMethod(g_cameraObject, g_stopPreviewMethodId);
Detach(env);
} }
void CameraPlatform_UpdateCapture() void CameraPlatform_UpdateCapture()

View File

@ -27,8 +27,7 @@ enum CameraMessage
CAMERA_STARTED, CAMERA_STARTED,
CAMERA_STOPPED, CAMERA_STOPPED,
CAMERA_NOT_PERMITTED, CAMERA_NOT_PERMITTED,
CAMERA_ERROR, CAMERA_ERROR
CAMERA_SHOW_PERMISSION_RATIONALE
}; };
extern int CameraPlatform_Initialize(); extern int CameraPlatform_Initialize();

View File

@ -26,8 +26,6 @@ local function start_capture(self)
end end
camera.start_capture(type, quality, function(self, status) camera.start_capture(type, quality, function(self, status)
print("camera.start_capture", status)
pprint(camera)
if status == camera.CAMERA_STARTED then if status == camera.CAMERA_STARTED then
self.cameraframe = camera.get_frame() self.cameraframe = camera.get_frame()
self.camerainfo = camera.get_info() self.camerainfo = camera.get_info()
@ -39,7 +37,9 @@ local function start_capture(self)
num_mip_maps=1 num_mip_maps=1
} }
label.set_text("logo#status", "Capture Status: ON") label.set_text("logo#status", "Capture Status: ON")
else elseif status == camera.CAMERA_STOPPED then
label.set_text("logo#status", "Capture Status: OFF")
elseif status == camera.CAMERA_ERROR then
label.set_text("logo#status", "Capture Status: ERROR") label.set_text("logo#status", "Capture Status: ERROR")
end end
end) end)