我找不到任何程序可以通过本机反应将用户正在做的事情从应用程序中传输出去。
我正在创建自己的插件
目标是将流从Java发送到javascript,然后通过socket.io将其发送到外部套接字服务器
这是我的Java类,要求授权和流
import android.hardware.display.DisplayManager;
import android.util.DisplayMetrics;
import android.app.Activity;
import android.content.Intent;
import android.media.projection.MediaProjectionManager;
import android.media.projection.MediaProjection;
import android.media.MediaRecorder;
import android.util.Log;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.BaseActivityEventListener;
import static android.content.Context.MEDIA_PROJECTION_SERVICE;
public class ScreenMirroringModule extends ReactContextBaseJavaModule {
private static final int SCREEN_SHARE_REQUEST = 4242;
private static final String S_MIRROR_CANCELLED = "S_MIRROR_CANCELLED";
private Promise sMirrorPromise;
private MediaProjectionManager mMediaProjectionManager;
private MediaStreamer mMediaStreamer = new MediaStreamer();
private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
if (requestCode == SCREEN_SHARE_REQUEST) {
if (sMirrorPromise != null) {
if (resultCode == Activity.RESULT_CANCELED) {
sMirrorPromise.reject(S_MIRROR_CANCELLED, "Screen mirroring was cancelled");
} else if (resultCode == Activity.RESULT_OK) {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
mMediaStreamer.reset();
mMediaStreamer.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaStreamer.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaStreamer.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaStreamer.setVideoSize(dm.widthPixels, dm.heightPixels);
mMediaStreamer.setVideoFrameRate(30);
StreamTask st = new StreamTask();
st.execute(mMediaStreamer);
try {
st.get();
} catch (Exception e) {
sMirrorPromise.reject(e);
}
MediaProjection mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, intent);
try {
mMediaProjection.createVirtualDisplay("MainActivity",
dm.widthPixels, dm.heightPixels, dm.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaStreamer.getSurface(), null /*Callbacks*/, null/*Handler*/);
mMediaStreamer.start();
} catch (Exception e) {
//Log.v("ReactNative", Log.getStackTraceString(e));
sMirrorPromise.reject(e);
}
sMirrorPromise.resolve("Test");
}
}
sMirrorPromise = null;
}
}
};
public ScreenMirroringModule(ReactApplicationContext reactContext) {
super(reactContext);
// Add the listener for `onActivityResult`
reactContext.addActivityEventListener(mActivityEventListener);
}
@Override
public String getName() {
return "ScreenMirroring";
}
@ReactMethod
public void stream(String ip, int port, Promise promise) {
final Activity activity = getCurrentActivity();
// Store the promise to resolve/reject when picker returns data
sMirrorPromise = promise;
mMediaProjectionManager = (MediaProjectionManager) activity.getSystemService(MEDIA_PROJECTION_SERVICE);
Intent intent = mMediaProjectionManager.createScreenCaptureIntent();
activity.startActivityForResult(intent, SCREEN_SHARE_REQUEST);
}
}
这是我的班,正在将录音转换成流
package com.ijkoareactapp;
import android.media.MediaRecorder;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
public class MediaStreamer extends MediaRecorder {
private LocalServerSocket localServerSocket = null;
private LocalSocket receiver, sender = null;
public void prepare() throws IllegalStateException, IOException {
receiver = new LocalSocket();
try {
localServerSocket = new LocalServerSocket("screen_mirror_socket");
receiver.connect(new LocalSocketAddress("screen_mirror_socket"));
receiver.setReceiveBufferSize(4096);
receiver.setSendBufferSize(4096);
sender = localServerSocket.accept();
sender.setReceiveBufferSize(4096);
sender.setSendBufferSize(4096);
} catch (Exception e) {
throw new IOException("Can't create local socket !");
}
setOutputFile(sender.getFileDescriptor());
try {
super.prepare();
} catch (Exception e) {
Log.v("ReactNative", Log.getStackTraceString(e));
closeSockets();
throw e;
}
}
public InputStream getInputStream() {
InputStream out = null;
try {
out = receiver.getInputStream();
} catch (IOException e) {
}
return out;
}
public void stop() {
closeSockets();
super.stop();
}
private void closeSockets() {
if (localServerSocket != null) {
try {
localServerSocket.close();
sender.close();
receiver.close();
} catch (IOException e) {
}
localServerSocket = null;
sender = null;
receiver = null;
}
}
}
这是在后台运行任务的类,因为我无法在主进程中启动本地套接字
package com.ijkoareactapp;
import android.os.AsyncTask;
import android.util.Log;
public class StreamTask extends AsyncTask <MediaStreamer, Integer, Long>{
protected Long doInBackground(MediaStreamer... mediaStreamers) {
Log.v("ReactNative", "Start");
for(int i = 0; i < mediaStreamers.length; i++) {
try {
mediaStreamers[i].prepare();
Log.v("ReactNative", "Prepared");
} catch (Exception e) {
Log.v("ReactNative", "Error");
Log.v("ReactNative", Log.getStackTraceString(e));
}
}
return null;
}
}
我的错误是
08-05 15:28:49.465 555 571 V ReactNative: java.lang.IllegalStateException
08-05 15:28:49.465 555 571 V ReactNative: at android.media.MediaRecorder._prepare(Native Method)
08-05 15:28:49.465 555 571 V ReactNative: at android.media.MediaRecorder.prepare(MediaRecorder.java:827)
08-05 15:28:49.465 555 571 V ReactNative: at com.ijkoareactapp.MediaStreamer.prepare(MediaStreamer.java:37)
08-05 15:28:49.465 555 571 V ReactNative: at com.ijkoareactapp.StreamTask.doInBackground(StreamTask.java:14)
08-05 15:28:49.465 555 571 V ReactNative: at com.ijkoareactapp.StreamTask.doInBackground(StreamTask.java:6)
08-05 15:28:49.465 555 571 V ReactNative: at android.os.AsyncTask$2.call(AsyncTask.java:304)
08-05 15:28:49.465 555 571 V ReactNative: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
08-05 15:28:49.465 555 571 V ReactNative: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
08-05 15:28:49.465 555 571 V ReactNative: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
08-05 15:28:49.465 555 571 V ReactNative: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
08-05 15:28:49.465 555 571 V ReactNative: at java.lang.Thread.run(Thread.java:761)
在阅读一些文档后,似乎prepare
在start
之前或setOutputFormat
之后被调用了。
我认为内部套接字连接未正确初始化,但找不到正确的方法。
同样不确定我应该将mMediaProjection.createVirtualDisplay
放在哪里,目前出现以下错误应该是因为prepare does not works
08-05 15:43:36.077 1575 1575 V ReactNative: java.lang.IllegalStateException: failed to get surface
08-05 15:43:36.077 1575 1575 V ReactNative: at android.media.MediaRecorder.getSurface(Native Method)
08-05 15:43:36.077 1575 1575 V ReactNative: at com.ijkoareactapp.ScreenMirroringModule$1.onActivityResult(ScreenMirroringModule.java:65)
08-05 15:43:36.077 1575 1575 V ReactNative: at com.facebook.react.bridge.ReactContext.onActivityResult(ReactContext.java:262)
08-05 15:43:36.077 1575 1575 V ReactNative: at com.facebook.react.ReactInstanceManager.onActivityResult(ReactInstanceManager.java:703)
08-05 15:43:36.077 1575 1575 V ReactNative: at com.facebook.react.ReactActivityDelegate.onActivityResult(ReactActivityDelegate.java:124)
08-05 15:43:36.077 1575 1575 V ReactNative: at com.facebook.react.ReactActivity.onActivityResult(ReactActivity.java:75)
08-05 15:43:36.077 1575 1575 V ReactNative: at android.app.Activity.dispatchActivityResult(Activity.java:6915)
08-05 15:43:36.077 1575 1575 V ReactNative: at android.app.ActivityThread.deliverResults(ActivityThread.java:4049)
08-05 15:43:36.077 1575 1575 V ReactNative: at android.app.ActivityThread.handleSendResult(ActivityThread.java:4096)
08-05 15:43:36.077 1575 1575 V ReactNative: at android.app.ActivityThread.-wrap20(ActivityThread.java)
08-05 15:43:36.077 1575 1575 V ReactNative: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1516)
08-05 15:43:36.077 1575 1575 V ReactNative: at android.os.Handler.dispatchMessage(Handler.java:102)
08-05 15:43:36.077 1575 1575 V ReactNative: at android.os.Looper.loop(Looper.java:154)
08-05 15:43:36.077 1575 1575 V ReactNative: at android.app.ActivityThread.main(ActivityThread.java:6077)
08-05 15:43:36.077 1575 1575 V ReactNative: at java.lang.reflect.Method.invoke(Native Method)
08-05 15:43:36.077 1575 1575 V ReactNative: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
08-05 15:43:36.077 1575 1575 V ReactNative: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
答案 0 :(得分:0)
很难在本地重现您的问题。 您可能对错了MediaStreamer初始化的顺序。 尝试逐行遵循以下顺序:
如果没有帮助,我有最好的建议-看一下React Native / Android项目,并尝试找出不同之处: https://github.com/ycswaves/react-native-screen-recorder/blob/master/android/app/src/main/java/com/screenrecorder/MainActivity.java#L131~L143 或这个: https://github.com/fyhertz/spydroid-ipcamera/blob/779f1035ac8fd91be5dfba99516da1b9f29f8768/src/net/majorkernelpanic/streaming/video/VideoStream.java#L339~L357
根据此存储库OutputFormat.MPEG_4并不是使用套接字的最佳选择。您想尝试THREE_GPP吗?
最后,您必须为您的应用添加其他权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
祝你好运!
答案 1 :(得分:0)
我可以更正您的ScreenMirroringModule
和StreamTask
来解决问题,
StreamTask
package com.ijkoareactapp;
import android.os.AsyncTask;
import android.util.Log;
public class StreamTask extends AsyncTask <MediaStreamer, Integer, Long>{
private StreamTaskStatus streamTaskStatus;
public StreamTask(StreamTaskStatus streamTaskStatus) {
this.streamTaskStatus = streamTaskStatus;
}
protected Long doInBackground(MediaStreamer... mediaStreamers) {
Log.v("ReactNative", "Start");
for(int i = 0; i < mediaStreamers.length; i++) {
try {
mediaStreamers[i].prepare();
Log.v("ReactNative", "Prepared");
} catch (Exception e) {
Log.v("ReactNative", "Error");
Log.v("ReactNative", Log.getStackTraceString(e));
}
}
return null;
}
public onPostExecute() {
if (this.streamTaskStatus != null) {
this.streamTaskStatus.streamTaskCompleted();
}
}
public interface StreamTaskStatus {
void streamTaskCompleted();
}
}
ScreenMirroringModule
import android.hardware.display.DisplayManager;
import android.util.DisplayMetrics;
import android.app.Activity;
import android.content.Intent;
import android.media.projection.MediaProjectionManager;
import android.media.projection.MediaProjection;
import android.media.MediaRecorder;
import android.util.Log;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.BaseActivityEventListener;
import static android.content.Context.MEDIA_PROJECTION_SERVICE;
public class ScreenMirroringModule extends ReactContextBaseJavaModule, implements StreamTaskStatus {
private static final int SCREEN_SHARE_REQUEST = 4242;
private static final String S_MIRROR_CANCELLED = "S_MIRROR_CANCELLED";
private Promise sMirrorPromise;
private StreamTask st;
private MediaProjectionManager mMediaProjectionManager;
private MediaStreamer mMediaStreamer = new MediaStreamer();
private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
if (requestCode == SCREEN_SHARE_REQUEST) {
if (sMirrorPromise != null) {
if (resultCode == Activity.RESULT_CANCELED) {
sMirrorPromise.reject(S_MIRROR_CANCELLED, "Screen mirroring was cancelled");
} else if (resultCode == Activity.RESULT_OK) {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
mMediaStreamer.reset();
mMediaStreamer.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaStreamer.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaStreamer.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaStreamer.setVideoSize(dm.widthPixels, dm.heightPixels);
mMediaStreamer.setVideoFrameRate(30);
st = new StreamTask(ScreenMirroringModule.this);
st.execute(mMediaStreamer);
}
}
sMirrorPromise = null;
}
}
};
public ScreenMirroringModule(ReactApplicationContext reactContext) {
super(reactContext);
// Add the listener for `onActivityResult`
reactContext.addActivityEventListener(mActivityEventListener);
}
@Override
public String getName() {
return "ScreenMirroring";
}
@Override
public void streamTaskCompleted() {
MediaProjection mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, intent);
try {
mMediaProjection.createVirtualDisplay("MainActivity",
dm.widthPixels, dm.heightPixels, dm.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaStreamer.getSurface(), null /*Callbacks*/, null/*Handler*/);
mMediaStreamer.start();
} catch (Exception e) {
//Log.v("ReactNative", Log.getStackTraceString(e));
sMirrorPromise.reject(e);
}
sMirrorPromise.resolve("Test");
}
@ReactMethod
public void stream(String ip, int port, Promise promise) {
final Activity activity = getCurrentActivity();
// Store the promise to resolve/reject when picker returns data
sMirrorPromise = promise;
mMediaProjectionManager = (MediaProjectionManager) activity.getSystemService(MEDIA_PROJECTION_SERVICE);
Intent intent = mMediaProjectionManager.createScreenCaptureIntent();
activity.startActivityForResult(intent, SCREEN_SHARE_REQUEST);
}
}
说明
您正在执行的操作是异步操作(使用异步任务),我们再次在主线程中等待,这可能导致了IllegalStateException
。
请检查是否有帮助,因为我没有可验证的Android工作室设置。
Lemme知道是否还有其他问题我会尽力帮助
更新
我可能会在此link中找到以下步骤,这是另一个缺少的东西,
开始录制视频-要成功录制视频,必须完成以下步骤:
警告:您必须在以下位置调用这些MediaRecorder配置方法 此顺序,否则您的应用程序将遇到错误,并且 录制将失败。
请注意警告,因为它表示我们必须遵循此顺序和步骤。
还要提供所需的各个摄像头权限。