From fa787d17517f499438887566be6f2d0b92353686 Mon Sep 17 00:00:00 2001 From: Xiang Silian Date: Wed, 10 Sep 2025 18:45:17 +0800 Subject: [PATCH] save code --- and_proj/app/build.gradle | 2 +- .../khronos/vulkan_samples/MainActivity.java | 73 +++---- .../vulkan_samples/VulkanTopActivity.java | 178 ++++++++++++++++++ 3 files changed, 220 insertions(+), 33 deletions(-) create mode 100644 app/android/java/com/khronos/vulkan_samples/VulkanTopActivity.java diff --git a/and_proj/app/build.gradle b/and_proj/app/build.gradle index 898811b..f205c01 100644 --- a/and_proj/app/build.gradle +++ b/and_proj/app/build.gradle @@ -8,7 +8,7 @@ apply from: "./download_vvl.gradle" android { ndkVersion '28.2.13676358' - compileSdk 35 + compileSdk 36 defaultConfig { applicationId 'com.khronos.vulkan_samples' diff --git a/app/android/java/com/khronos/vulkan_samples/MainActivity.java b/app/android/java/com/khronos/vulkan_samples/MainActivity.java index 5d6053a..78adee6 100644 --- a/app/android/java/com/khronos/vulkan_samples/MainActivity.java +++ b/app/android/java/com/khronos/vulkan_samples/MainActivity.java @@ -2,47 +2,61 @@ package com.khronos.vulkan_samples; import android.Manifest; -import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.SurfaceTexture; import android.os.Bundle; import android.util.Log; +import android.view.Surface; +import android.view.SurfaceView; +import android.view.TextureView; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; +import android.widget.FrameLayout; import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.camera.core.Camera; import androidx.camera.core.CameraSelector; import androidx.camera.core.Preview; +import androidx.camera.core.SurfaceRequest; import androidx.camera.lifecycle.ProcessCameraProvider; -import androidx.camera.view.PreviewView; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import com.google.androidgamesdk.GameActivity; import com.google.common.util.concurrent.ListenableFuture; -import com.google.mediapipe.examples.facelandmarker.FaceLandmarkerHelper; - import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; public class MainActivity extends GameActivity { - private PreviewView previewView; + private TextureView textureView; // 使用 TextureView 替代 PreviewView private ProcessCameraProvider cameraProvider; + private FrameLayout containerLayout; private void initCamera(){ - // 创建摄像头预览视图 - previewView = new PreviewView(this); - previewView.setImplementationMode(PreviewView.ImplementationMode.COMPATIBLE); - previewView.setScaleType(PreviewView.ScaleType.FILL_CENTER); + // 获取 GameActivity 的根视图 + ViewGroup rootView = (ViewGroup) getWindow().getDecorView(); - addContentView(previewView, new ViewGroup.LayoutParams( + // 创建容器布局 + containerLayout = new FrameLayout(this); + containerLayout.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT )); - bringVulkanToFront(); + // 创建 TextureView 用于摄像头预览 + textureView = new TextureView(this); + textureView.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )); + + // 将 TextureView 添加到容器 + containerLayout.addView(textureView); + + // 将容器添加到根视图的底部(作为背景) + //rootView.addView(containerLayout); // 添加到索引0(最底层) + rootView.addView(containerLayout, 0); + if (hasCameraPermission()) { startCamera(); @@ -51,23 +65,6 @@ public class MainActivity extends GameActivity { } } - private void bringVulkanToFront() { - // 获取窗口的根视图 - View rootView = getWindow().getDecorView(); - if (rootView instanceof ViewGroup) { - ViewGroup rootGroup = (ViewGroup) rootView; - - for (int i = rootGroup.getChildCount() - 1; i >= 0; i--) { - View child = rootGroup.getChildAt(i); - if (child != previewView) { - child.bringToFront(); - child.setBackgroundColor(Color.TRANSPARENT); - break; - } - } - } - } - @Override protected void onCreate(Bundle savedInstanceState) { @@ -115,7 +112,18 @@ public class MainActivity extends GameActivity { .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build(); - preview.setSurfaceProvider(previewView.getSurfaceProvider()); + // 使用 TextureView 的 SurfaceTexture + SurfaceTexture surfaceTexture = textureView.getSurfaceTexture(); + if (surfaceTexture != null) { + Surface surface = new Surface(surfaceTexture); + preview.setSurfaceProvider(new Preview.SurfaceProvider() { + @Override + public void onSurfaceRequested(@NonNull SurfaceRequest request) { + request.provideSurface(surface, ContextCompat.getMainExecutor(MainActivity.this), + result -> {}); + } + }); + } cameraProvider.bindToLifecycle(this, cameraSelector, preview); @@ -125,6 +133,7 @@ public class MainActivity extends GameActivity { }, ContextCompat.getMainExecutor(this)); } + private static final int REQUEST_CODE_PERMISSIONS = 1001; private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA}; private static final String TAG = "MainActivity"; diff --git a/app/android/java/com/khronos/vulkan_samples/VulkanTopActivity.java b/app/android/java/com/khronos/vulkan_samples/VulkanTopActivity.java new file mode 100644 index 0000000..54fab97 --- /dev/null +++ b/app/android/java/com/khronos/vulkan_samples/VulkanTopActivity.java @@ -0,0 +1,178 @@ +package com.khronos.vulkan_samples; + + +import android.Manifest; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.SurfaceTexture; +import android.os.Bundle; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceView; +import android.view.TextureView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.camera.core.CameraSelector; +import androidx.camera.core.Preview; +import androidx.camera.core.SurfaceRequest; +import androidx.camera.lifecycle.ProcessCameraProvider; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.google.androidgamesdk.GameActivity; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.ExecutionException; + +public class VulkanTopActivity extends GameActivity { + private TextureView textureView; // 使用 TextureView 替代 PreviewView + private ProcessCameraProvider cameraProvider; + private void initCamera(){ + // 创建 TextureView + textureView = new TextureView(this); + textureView.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )); + + // 获取根视图并添加 TextureView 作为背景 + ViewGroup rootView = (ViewGroup) getWindow().getDecorView(); + rootView.addView(textureView, 0); // 添加到最底层 + + // 配置 Vulkan 视图透明度 + setupVulkanView(); + + if (hasCameraPermission()) { + startCamera(); + } else { + requestCameraPermission(); + } + } + + private void setupVulkanView() { + ViewGroup rootView = (ViewGroup) getWindow().getDecorView(); + + for (int i = 0; i < rootView.getChildCount(); i++) { + View child = rootView.getChildAt(i); + if (child instanceof SurfaceView && child != textureView) { + SurfaceView vulkanView = (SurfaceView) child; + + // 关键设置:确保 Vulkan 视图在顶层且透明 + vulkanView.setZOrderOnTop(true); + vulkanView.getHolder().setFormat(PixelFormat.TRANSPARENT); + vulkanView.setBackgroundColor(Color.TRANSPARENT); + + // 确保它在最前面 + vulkanView.bringToFront(); + break; + } + } + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + String native_lib_name = getResources().getString(R.string.native_lib_name); + try { + System.loadLibrary(native_lib_name); + } catch (UnsatisfiedLinkError e) { + Toast.makeText(getApplicationContext(), "Native code library failed to load.", Toast.LENGTH_SHORT).show(); + } + String[] argArray = new String[2]; + argArray[0] = "sample"; + argArray[1] = "hello_triangle"; +// sendArgumentsToPlatform(argArray); + super.onCreate(savedInstanceState); + + initCamera(); + + Log.i("MainActivity", "onCreate: "); + } + + private boolean hasCameraPermission() { + return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) + == PackageManager.PERMISSION_GRANTED; + } + + private void requestCameraPermission() { + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.CAMERA}, + REQUEST_CAMERA_PERMISSION); + } + + private static final int REQUEST_CAMERA_PERMISSION = 1001; + + private void startCamera() { + ListenableFuture cameraProviderFuture = + ProcessCameraProvider.getInstance(this); + + cameraProviderFuture.addListener(() -> { + try { + cameraProvider = cameraProviderFuture.get(); + Preview preview = new Preview.Builder().build(); + CameraSelector cameraSelector = new CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build(); + + textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { + @Override + public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surfaceTexture, int width, int height) { + Surface surface = new Surface(surfaceTexture); + preview.setSurfaceProvider(request -> { + request.provideSurface(surface, ContextCompat.getMainExecutor(VulkanTopActivity.this), + result -> {}); + }); + + cameraProvider.bindToLifecycle(VulkanTopActivity.this, cameraSelector, preview); + } + + @Override + public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surfaceTexture, int width, int height) {} + + @Override + public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surfaceTexture) { + return false; + } + + @Override + public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surfaceTexture) {} + }); + + } catch (ExecutionException | InterruptedException e) { + Log.e("MainActivity", "Error starting camera: " + e.getMessage()); + } + }, ContextCompat.getMainExecutor(this)); + } + + + private static final int REQUEST_CODE_PERMISSIONS = 1001; + private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA}; + private static final String TAG = "MainActivity"; + + private boolean allPermissionsGranted() { + for (String permission : REQUIRED_PERMISSIONS) { + if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + return true; + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == REQUEST_CODE_PERMISSIONS) { + if (allPermissionsGranted()) { + startCamera(); + } else { + Log.e(TAG, "Permissions not granted by the user."); + finish(); // Close the activity if permission is denied + } + } + } + +// private native void sendArgumentsToPlatform(String[] args); +} \ No newline at end of file