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 +++++++++++++++++++++++++++++++++++++++-------
app/src/main/java/com/safeluck/floatwindow/MainActivity.kt | 2
2 files changed, 118 insertions(+), 24 deletions(-)
diff --git a/app/src/main/java/com/safeluck/floatwindow/MainActivity.kt b/app/src/main/java/com/safeluck/floatwindow/MainActivity.kt
index 5d7335d..437b645 100644
--- a/app/src/main/java/com/safeluck/floatwindow/MainActivity.kt
+++ b/app/src/main/java/com/safeluck/floatwindow/MainActivity.kt
@@ -178,7 +178,7 @@
codeRate = 0
frameRate = 0
m_screen = MediaArgu.ScreenSolution(640, 480) // 榛樿鍒嗚鲸鐜�
- url = "rtmp://your-push-url" // TODO: 闇�瑕佽缃疄闄呯殑鎺ㄦ祦鍦板潃
+ url = "rtmp://192.168.16.143/live/livestream" // TODO: 闇�瑕佽缃疄闄呯殑鎺ㄦ祦鍦板潃
userName = ""
pwd = ""
}
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