保存代码
This commit is contained in:
+86
-16
@@ -16,6 +16,7 @@ FaceApp* g_Application = nullptr;
|
||||
AAssetManager* g_assetManager = nullptr;
|
||||
|
||||
jobject g_callback = nullptr;
|
||||
jobject g_callbackAnimationFinished = nullptr;
|
||||
|
||||
void handle_cmd(android_app *pApp, int32_t cmd) {
|
||||
switch (cmd) {
|
||||
@@ -149,22 +150,7 @@ Java_com_hmwl_face_1sdk_FaceActivity_SetCppInitArg(JNIEnv *env, jobject thiz, js
|
||||
}
|
||||
memcpy(g_InitArgString, nativeString, len);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hmwl_face_1sdk_FaceActivity_ChangeStateCpp(JNIEnv *env, jobject thiz, jstring json) {
|
||||
// TODO: implement ChangeStateCpp()
|
||||
const char *nativeString = env->GetStringUTFChars(json, nullptr);
|
||||
jsize len = env->GetStringUTFLength(json);
|
||||
if(len > ArgLen)
|
||||
{
|
||||
aout << "ArgLen to long:" << len << std::endl;
|
||||
return;
|
||||
}
|
||||
if(g_Application->isInited())
|
||||
{
|
||||
g_Application->changeMotion(nativeString);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hmwl_face_1sdk_FaceActivity_StopRunning(JNIEnv *env, jobject thiz) {
|
||||
@@ -241,6 +227,63 @@ void CppCallback(const string& motion_type)
|
||||
}
|
||||
|
||||
|
||||
void CppAnimationFinishedCallback()
|
||||
{
|
||||
JNIEnv* env = nullptr;
|
||||
bool needDetach = false;
|
||||
|
||||
// 获取当前线程的 JNIEnv
|
||||
JavaVM* vm = g_jvm; // 你需要提前保存 JavaVM* 到全局变量 g_jvm
|
||||
int status = vm->GetEnv((void**)&env, JNI_VERSION_1_6);
|
||||
if (status == JNI_EDETACHED) {
|
||||
// 当前线程未 attach,需 attach
|
||||
if (vm->AttachCurrentThread(&env, nullptr) != 0) {
|
||||
return;
|
||||
}
|
||||
needDetach = true;
|
||||
} else if (status != JNI_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_callbackAnimationFinished == nullptr) {
|
||||
if (needDetach) vm->DetachCurrentThread();
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 获取 CallbackInterface 的 class
|
||||
jclass callbackClass = env->GetObjectClass(g_callbackAnimationFinished);
|
||||
if (callbackClass == nullptr) {
|
||||
if (needDetach) vm->DetachCurrentThread();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 获取 OnLoadActionFinished 方法 ID(注意方法名大小写必须一致!)
|
||||
jmethodID methodId = env->GetMethodID(callbackClass, "OnAnimationFinished", "()V");
|
||||
if (methodId == nullptr) {
|
||||
env->ExceptionDescribe(); // 打印异常
|
||||
env->ExceptionClear();
|
||||
if (needDetach) vm->DetachCurrentThread();
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 调用 Java 回调
|
||||
env->CallVoidMethod(g_callbackAnimationFinished, methodId);
|
||||
|
||||
// 5. 检查是否抛出异常
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
}
|
||||
|
||||
env->DeleteLocalRef(callbackClass);
|
||||
|
||||
// 7. 如果是临时 attach 的线程,要 detach
|
||||
if (needDetach) {
|
||||
vm->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jstring JNICALL
|
||||
@@ -269,3 +312,30 @@ Java_com_hmwl_face_1sdk_FaceActivity_PreReadAction(JNIEnv *env, jobject thiz, js
|
||||
std::string ret = g_Application->preReadyMotion(nativeString, CppCallback);
|
||||
return env->NewStringUTF(ret.c_str());
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hmwl_face_1sdk_FaceActivity_ChangeMotionCpp(JNIEnv *env, jobject thiz, jstring json,
|
||||
jobject callback, jboolean loop) {
|
||||
// TODO: implement ChangeMotionCpp()
|
||||
const char *nativeString = env->GetStringUTFChars(json, nullptr);
|
||||
jsize len = env->GetStringUTFLength(json);
|
||||
if(len > ArgLen)
|
||||
{
|
||||
aout << "ArgLen to long:" << len << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存新的回调
|
||||
if (callback != nullptr) {
|
||||
g_callbackAnimationFinished = env->NewGlobalRef(callback);
|
||||
} else {
|
||||
g_callbackAnimationFinished = nullptr;
|
||||
}
|
||||
|
||||
if(g_Application->isInited())
|
||||
{
|
||||
g_Application->changeMotion(nativeString, CppAnimationFinishedCallback, loop);
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,21 @@ public class FaceActivity extends GameActivity implements FaceLandmarkerHelper.L
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
if (requestCode == REQUEST_CAMERA_PERMISSION) {
|
||||
// 检查权限是否被授予
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// 用户授予了权限,启动相机
|
||||
startCamera();
|
||||
} else {
|
||||
requestCameraPermission();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startCamera() {
|
||||
ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
|
||||
ProcessCameraProvider.getInstance(this);
|
||||
@@ -276,15 +291,19 @@ public class FaceActivity extends GameActivity implements FaceLandmarkerHelper.L
|
||||
void OnLoadActionFinished(String result);
|
||||
}
|
||||
|
||||
public interface AnimationFinishedCallbackInterface {
|
||||
void OnAnimationFinished();
|
||||
}
|
||||
|
||||
protected native String PreReadAction(String motion, CallbackInterface callback);
|
||||
protected String PreLoadAction(String json, CallbackInterface callback){
|
||||
return PreReadAction(json, callback);
|
||||
}
|
||||
|
||||
protected native void ChangeStateCpp(String json);
|
||||
protected void ChangeMotion(String json){
|
||||
protected native void ChangeMotionCpp(String json, AnimationFinishedCallbackInterface callback, boolean loop);
|
||||
protected void ChangeMotion(String json, AnimationFinishedCallbackInterface callback, boolean loop){
|
||||
Log.i("FaceActivity", "ChangeState:" + json);
|
||||
ChangeStateCpp(json);
|
||||
ChangeMotionCpp(json, callback, loop);
|
||||
}
|
||||
|
||||
// 添加这个缺失的方法
|
||||
|
||||
@@ -4,8 +4,11 @@ package com.inewme.uvmirror
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.KeyEvent.KEYCODE_BACK
|
||||
import android.view.MotionEvent
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import com.hmwl.face_sdk.FaceActivity
|
||||
import com.hmwl.face_sdk.InitArg
|
||||
import com.hmwl.face_sdk.Motion
|
||||
@@ -38,12 +41,31 @@ class MakeupActivity : FaceActivity()
|
||||
override fun OnLoadActionFinished(motion_type: String) {
|
||||
//加载完成后,切断到对应的动画
|
||||
Log.i("info","加载完成后,切换到对应的动画")
|
||||
ChangeMotion(motion_type)
|
||||
ChangeMotion(motion_type, object : AnimationFinishedCallbackInterface{
|
||||
override fun OnAnimationFinished(){
|
||||
Log.i("info","动画播放完成,收到回调")
|
||||
}
|
||||
}, false)
|
||||
}
|
||||
})
|
||||
Toast.makeText(this, "开始加载动画: $result", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
if (keyCode == KEYCODE_BACK) {
|
||||
Log.d("MakeupActivity", "Back key pressed")
|
||||
handleBackPress()
|
||||
return true // 消费事件,防止默认行为(如直接 finish)
|
||||
}
|
||||
return super.onKeyDown(keyCode, event)
|
||||
}
|
||||
|
||||
private fun handleBackPress() {
|
||||
Stop()
|
||||
finish()
|
||||
}
|
||||
|
||||
|
||||
private fun getMotionByIndex(index: Int): Motion {
|
||||
pngFilesByFolder?.let { folders ->
|
||||
val motion = Motion().apply {
|
||||
@@ -98,7 +120,11 @@ class MakeupActivity : FaceActivity()
|
||||
else
|
||||
{
|
||||
//手动切换动画
|
||||
ChangeMotion(nextMotionType);
|
||||
ChangeMotion(nextMotionType, object: AnimationFinishedCallbackInterface{
|
||||
override fun OnAnimationFinished(){
|
||||
Log.i("info","动画播放完成的回调")
|
||||
}
|
||||
}, false);
|
||||
nextMotionLoadFinished = false;
|
||||
curIndex++;
|
||||
Toast.makeText(this, "切换到下一个动画 $nextMotionType", Toast.LENGTH_SHORT).show()
|
||||
|
||||
+15
-1
@@ -1321,9 +1321,21 @@ void FaceApp::drawFrame(long long frameTime)
|
||||
{
|
||||
_curTexIndex++;
|
||||
if (_curTexIndex >= _curMotion_png_size)
|
||||
{
|
||||
if(_animationFinishedCallback != nullptr)
|
||||
{
|
||||
_animationFinishedCallback();
|
||||
}
|
||||
|
||||
if (_animationLoop)
|
||||
{
|
||||
_curTexIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_curTexIndex = _curMotion_png_size - 1;
|
||||
}
|
||||
}
|
||||
game_time = game_time - actionTime;
|
||||
}
|
||||
Application::drawFrame(frameTime);
|
||||
@@ -1357,7 +1369,7 @@ string FaceApp::preReadyMotion(const std::string& json, Callback callback)
|
||||
return "failure";
|
||||
}
|
||||
|
||||
void FaceApp::changeMotion(const string motion_type)
|
||||
void FaceApp::changeMotion(const string motion_type, AnimationFinishedCallback callback, bool loop)
|
||||
{
|
||||
if (_curMotion_type == motion_type)
|
||||
{
|
||||
@@ -1387,6 +1399,8 @@ void FaceApp::changeMotion(const string motion_type)
|
||||
_curMotion_type = motion_type;
|
||||
_curMotion_png_size = _nextMotion.png_names.size();
|
||||
_motionState = ready;
|
||||
_animationFinishedCallback = callback;
|
||||
_animationLoop = loop;
|
||||
|
||||
|
||||
// for (int i = 0; i < _curMotion.png_names.size(); ++i)
|
||||
|
||||
+4
-1
@@ -35,6 +35,7 @@ struct PushConstants {
|
||||
};
|
||||
|
||||
using Callback = std::function<void(const std::string&)>;
|
||||
using AnimationFinishedCallback = std::function<void()>;
|
||||
|
||||
class FaceApp :public Application
|
||||
{
|
||||
@@ -139,8 +140,10 @@ private:
|
||||
|
||||
public:
|
||||
Callback _callback;
|
||||
AnimationFinishedCallback _animationFinishedCallback;
|
||||
bool _animationLoop = true;
|
||||
string preReadyMotion(const std::string& json, Callback callback);
|
||||
void changeMotion(const string motion_type);
|
||||
void changeMotion(const string motion_type, AnimationFinishedCallback callback, bool loop);
|
||||
//void changeMotion(Motion& motion);
|
||||
InitArg _initArg;
|
||||
//Motion _curMotion;
|
||||
|
||||
+8
-1
@@ -41,11 +41,18 @@ std::wstring ReadFileWithChinesePath(const std::wstring& filePath) {
|
||||
|
||||
FaceApp* g_app;
|
||||
|
||||
|
||||
void CppAnimationFinishedCallback()
|
||||
{
|
||||
std::cout << "call CppAnimationFinishedCallback\n";
|
||||
}
|
||||
|
||||
void CppCallback(const string& motion_type)
|
||||
{
|
||||
g_app->changeMotion(motion_type.c_str());
|
||||
g_app->changeMotion(motion_type.c_str(), CppAnimationFinishedCallback, true);
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
//std::string path = "chinese.txt";
|
||||
|
||||
Reference in New Issue
Block a user