From c2fa1b1cbd31cad492b24a508fd3990bf8089a10 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期三, 28 一月 2026 11:19:35 +0800
Subject: [PATCH] 1.SurfaceView 在 Service 中创建,但没有被添加到可见的 View hierarchy,因此 Surface 不会被创建,surfaceCreated 不会触发。   修复内容:   添加了 WindowManager:用于管理隐藏的 Window   将 SurfaceView 添加到隐藏的 Window:   创建 1x1 像素的隐藏 Window   设置为完全透明(alpha = 0.0f)   移到屏幕外(x = -1000, y = -1000)   使用 TYPE_APPLICATION_OVERLAY 或 TYPE_APPLICATION 类型   在释放资源时移除 Window:确保资源正确释放   2.  在收到onPreviewStarted的时候,延迟1秒进行调用startpushAsync,否则状态不对不会push

---
 app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java |  140 +++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 117 insertions(+), 23 deletions(-)

diff --git a/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java b/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
index 945ca9f..97ba0b8 100644
--- a/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
+++ b/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
@@ -1,6 +1,11 @@
 package com.safeluck.floatwindow.manager;
 
 import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.WindowManager;
 
 import com.alivc.live.pusher.AlivcAudioAACProfileEnum;
 import timber.log.Timber;
@@ -35,12 +40,14 @@
     // 闃块噷鎺ㄦ祦鐩稿叧
     private AlivcLivePusher alivcPusher;
     private AlivcLivePushConfig alivcLivePushConfig;
+    private SurfaceView previewSurfaceView;
     
     // USB鎽勫儚澶寸浉鍏�
     private UsbCamera usbCamera;
     private PushThread pushThread;
     private boolean isRunning = false;
     private boolean cameraExists = false;
+    private volatile boolean pushStarted = false;
     
     // 鎺ㄦ祦URL
     private String pushUrl;
@@ -50,6 +57,9 @@
     
     // 鏄惁寮�鍚憚鍍忓ご鍔犲瘑
     private boolean ay_encrypt = false;
+    
+    // 棰勮 SurfaceView 鍜岄殣钘忕殑 Window
+    private WindowManager windowManager;
     
     /**
      * 鎺ㄦ祦鍥炶皟鎺ュ彛
@@ -96,6 +106,7 @@
         try {
             // 鍒濆鍖栨帹娴丼DK
             initAlivcPusher();
+            pushStarted = false;
             
             // 妫�鏌ュ苟鎵撳紑USB鎽勫儚澶�
             if (!openUsbCamera()) {
@@ -106,11 +117,9 @@
             
             cameraExists = true;
             Timber.d("USB鎽勫儚澶存墦寮�鎴愬姛");
+
             
-            // 鍚姩鎽勫儚澶存暟鎹帹閫佺嚎绋�
-            startPushThread();
-            
-            notifyCallback(1, 0, "鎺ㄦ祦宸插惎鍔�");
+            notifyCallback(1, 0, "鎺ㄦ祦绾跨▼宸插惎鍔紝绛夊緟鎺ㄦ祦鐘舵�佸氨缁�");
         } catch (Exception e) {
             Timber.e(e, "Failed to start push");
             notifyCallback(1, -3, "鍚姩鎺ㄦ祦澶辫触: " + e.getMessage());
@@ -127,6 +136,7 @@
         if (usbCamera != null) {
             usbCamera.stopCamera();
         }
+        pushStarted = false;
         notifyCallback(1, 4, "鎺ㄦ祦宸插仠姝�");
     }
     
@@ -171,7 +181,72 @@
             // 鍒濆鍖栨帹娴佸櫒
             alivcPusher = new AlivcLivePusher();
             alivcPusher.init(context.getApplicationContext(), alivcLivePushConfig);
+
+            // 澶栭儴鑷畾涔夋祦妯″紡涓嬶紝鍚屾牱闇�瑕佸厛寮�鍚瑙堬紝璁╃姸鎬佷粠 INIT 杩涘叆 PREVIEWED
+            // 鍒涘缓涓�涓殣钘忕殑 Window 鏉ユ壙杞� SurfaceView锛岀‘淇� Surface 鑳藉琚垱寤�
+            windowManager = (WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
+            previewSurfaceView = new SurfaceView(context.getApplicationContext());
             
+            // 鍦� SurfaceView 鐨� surfaceCreated 鍥炶皟涓啀鍚姩棰勮锛岀‘淇� Surface 宸茬粡鍒涘缓
+            previewSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
+                @Override
+                public void surfaceCreated(SurfaceHolder holder) {
+                    try {
+                        Timber.d("previewSurfaceView surfaceCreated, startPreviewAysnc");
+                        if (alivcPusher != null) {
+                            alivcPusher.startPreviewAysnc(previewSurfaceView);
+
+
+
+                            // 鍚姩鎽勫儚澶存暟鎹帹閫佺嚎绋�
+                            startPushThread();
+                        }
+                    } catch (Exception e) {
+                        Timber.e(e, "startPreviewAysnc in surfaceCreated failed");
+                        notifyCallback(1, -3, "棰勮鍚姩澶辫触: " + e.getMessage());
+                    }
+                }
+
+                @Override
+                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+                    Timber.d("previewSurfaceView surfaceChanged: %dx%d", width, height);
+                }
+
+                @Override
+                public void surfaceDestroyed(SurfaceHolder holder) {
+                    Timber.d("previewSurfaceView surfaceDestroyed");
+                }
+            });
+            
+            // 灏� SurfaceView 娣诲姞鍒伴殣钘忕殑 Window 涓紝杩欐牱 Surface 鎵嶄細琚垱寤�
+            WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+                    1, 1, // 1x1 鍍忕礌锛屽嚑涔庝笉鍙
+                    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                            | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                            | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+                    android.graphics.PixelFormat.TRANSLUCENT
+            );
+            params.x = -1000; // 绉诲埌灞忓箷澶�
+            params.y = -1000;
+            params.alpha = 0.0f; // 瀹屽叏閫忔槑
+            
+            try {
+                windowManager.addView(previewSurfaceView, params);
+                Timber.d("previewSurfaceView added to window");
+            } catch (Exception e) {
+                Timber.e(e, "Failed to add previewSurfaceView to window");
+                // 濡傛灉娣诲姞澶辫触锛屽皾璇曚娇鐢� TYPE_APPLICATION 绫诲瀷
+                params.type = WindowManager.LayoutParams.TYPE_APPLICATION;
+                try {
+                    windowManager.addView(previewSurfaceView, params);
+                    Timber.d("previewSurfaceView added to window with TYPE_APPLICATION");
+                } catch (Exception e2) {
+                    Timber.e(e2, "Failed to add previewSurfaceView with TYPE_APPLICATION");
+                }
+            }
+
             // 璁剧疆鐩戝惉鍣�
             setupListeners();
             
@@ -181,7 +256,8 @@
             notifyCallback(1, -3, "鍒濆鍖栨帹娴丼DK澶辫触: " + e.getMessage());
         }
     }
-    
+
+    private Handler mainHandler = new Handler(Looper.getMainLooper());
     /**
      * 璁剧疆鐩戝惉鍣�
      */
@@ -191,22 +267,21 @@
             @Override
             public void onPreviewStarted(AlivcLivePusher alivcLivePusher) {
                 Timber.d("onPreviewStarted");
-                android.os.Handler handler = new android.os.Handler(android.os.Looper.getMainLooper());
-                handler.postDelayed(new Runnable() {
-                    @Override
-                    public void run() {
-                        if (alivcPusher != null && 
-                            alivcPusher.getCurrentStatus() != AlivcLivePushStats.PREVIEWED && 
-                            alivcPusher.getCurrentStatus() != AlivcLivePushStats.PUSHED) {
-                            Timber.w("Preview鐘舵�佸紓甯�");
-                        } else {
-                            if (cameraExists && pushUrl != null && !pushUrl.isEmpty()) {
-                                Timber.d("寮�濮嬫帹娴�: %s", pushUrl);
-                                alivcPusher.startPushAysnc(pushUrl);
-                            }
+                mainHandler.postDelayed(()->{
+                    // 棰勮灏辩华鍚庡啀鍚姩鎺ㄦ祦锛岄伩鍏� INIT 鐘舵�佺洿鎺� startPush 鎶ラ敊
+                    if (alivcPusher != null && pushUrl != null && !pushUrl.isEmpty()) {
+                        try {
+                            AlivcLivePushStats s = alivcPusher.getCurrentStatus();
+                            Timber.i("onPreviewStarted, current status=%s", s != null ? s.name() : "null");
+                            Timber.d("寮�濮嬫帹娴�: %s", pushUrl);
+                            alivcPusher.startPushAysnc(pushUrl);
+                        } catch (Exception e) {
+                            Timber.e(e, "startPushAysnc failed");
+                            notifyCallback(1, -3, "鍚姩鎺ㄦ祦澶辫触: " + e.getMessage());
                         }
                     }
-                }, 1000);
+                },1000);
+
             }
             
             @Override
@@ -217,6 +292,7 @@
             @Override
             public void onPushStarted(AlivcLivePusher alivcLivePusher) {
                 Timber.d("onPushStarted");
+                pushStarted = true;
                 notifyCallback(1, 0, "鎺ㄦ祦宸插紑濮嬶紝鍒嗚鲸鐜�: " + resolutionArr[0] + "x" + resolutionArr[1]);
             }
             
@@ -233,6 +309,7 @@
             @Override
             public void onPushStoped(AlivcLivePusher alivcLivePusher) {
                 Timber.d("onPushStoped");
+                pushStarted = false;
                 notifyCallback(1, 4, "鎺ㄦ祦宸插仠姝�");
             }
             
@@ -381,8 +458,8 @@
             // 鎵撳紑鎽勫儚澶翠箣鍓嶅厛璋冪敤setenv
             usbCamera.setenv();
 
-            // 浣跨敤prepareCamera鏂规硶锛宑amera_id鑼冨洿[0,9]
-            int[] cameraIds = {0, 9};
+            // 浣跨敤prepareCamera鏂规硶锛宑amera_id鑼冨洿[0,2]
+            int[] cameraIds = {0, 2};
             String cameraName = null; // 涓嶆寚瀹氱壒瀹氬悕绉�
 
             // 濡傛灉杩斿洖闈�0锛屼唬琛ㄦ墦寮�澶辫触锛屽垯鍏坰topCamera鍐嶉噸璇曪紝鏈�澶�3娆�
@@ -437,6 +514,17 @@
      * 閲婃斁闃块噷鎺ㄦ祦璧勬簮
      */
     private void releaseAlivcPusher() {
+        // 绉婚櫎闅愯棌鐨� SurfaceView
+        if (previewSurfaceView != null && windowManager != null) {
+            try {
+                windowManager.removeView(previewSurfaceView);
+                Timber.d("previewSurfaceView removed from window");
+            } catch (Exception e) {
+                Timber.e(e, "Error removing previewSurfaceView from window");
+            }
+            previewSurfaceView = null;
+        }
+        
         if (alivcPusher != null) {
             try {
                 AlivcLivePushStats stats = alivcPusher.getCurrentStatus();
@@ -453,6 +541,7 @@
             alivcPusher = null;
         }
         alivcLivePushConfig = null;
+        pushStarted = false;
     }
     
     /**
@@ -467,6 +556,7 @@
             try {
                 int width = resolutionArr[0];
                 int height = resolutionArr[1];
+                final long startTimeNs = System.nanoTime();
                 
                 // 璁$畻YUV420缂撳啿鍖哄ぇ灏�
                 int bufferSize = width * height * 3 / 2;
@@ -489,19 +579,23 @@
                     usbCamera.rgba(1, buffer);
                     
                     // 鎺ㄦ祦鏁版嵁鍒伴樋閲屼簯
-                    if (alivcPusher != null && cameraExists) {
+                    if (alivcPusher != null && cameraExists && pushStarted) {
                         try {
+                            long ptsUs = (System.nanoTime() - startTimeNs) / 1000;
                             alivcPusher.inputStreamVideoData(
                                     buffer,
                                     width,
                                     height,
                                     buffer.length,
-                                    System.nanoTime() / 1000, // 杞崲涓哄井绉�
+                                    ptsUs, // 鍗曡皟閫掑鐨勬椂闂存埑锛堝井绉掞級
                                     0 // rotation
                             );
                         } catch (Exception e) {
                             Timber.e(e, "Error pushing frame");
                         }
+                    } else if (!pushStarted) {
+                        // 绛夊緟 onPushStarted 鍚庡啀鍠傚抚锛岄伩鍏� SDK invalid state
+                        Thread.sleep(20);
                     }
                     
                     // 鎺у埗甯х巼锛岀害20fps

--
Gitblit v1.8.0