java.lang.NullPointerException: getSurface(...) must not be null
When I use GenericFromFile and push local files, I get java.lang.NullPointerException: getSurface(...) must not be null I can confirm that I have implemented the method according to the steps in the document, surfaceView = OpenGlView(context!!) bindingFloatWindow?.frameSurfaceView?.addView(surfaceView) genericFromFile = GenericFromFile(openGlView, this, this, this) It sometimes works, but sometimes it doesn't, and the above error will appear
Hello,
Are you doing the startStream after the preview is inflated like in the example? (Using the onSurfaceChanged callback)
Can you share the code where you are doing startStream?
I added a callback but did not do anything. Because my OpenGlView preview interface is on a float window, when I call startstream, the above error is reported directly. Here is the startStream method
No matter if you are in a float window. You need wait until that callback is called or the surface will be null or invalid. You can try add a delay to start stream but it is not a secure way to do it
I can confirm that my startStream event is executed after surfaceChanged:Surface(name=null)/@0xf77b5a8 has been executed and has a value. Does it have anything to do with the activity where the float is located?
I'm not sure about it but that surface is not ready for some reason. Maybe the surface is created, destroyed and re created. You can check if the surface if ready using this:
surfaceView.holder.surface.isValid
Also, remember that if your preview was detroyed and you need use a different preview you need change the preview:
//go to background, no preview available
genericFromFile.replaceView(context)
//the preview object changed, replace preview with the new view
genericFromFile.replaceView(openglView)
I can help you more if you are able to share a full code example.
This is the log I printed. Can you help me analyze it? Thanks to the author
This is the status judgment when the push starts, showing that it is ready
I will need a full code example to reproduce the error. Can you share me a minimal code example? You can share it using email if you want: [email protected]
It's not that I don't want to post it, it's that my apk is hooked through xposed. This OpenGlView uses the acitivity environment intercepted by the host app, and then a floating window pops up on it. It has been working fine before, but suddenly the host app has been updated. I used your library to push the stream. All the codes are normal, but this problem occurred when I started pushing the stream. So I want to ask you whether it is related to the opengl environment of the app used.
I did a fix for it: https://github.com/pedroSG94/RootEncoder/pull/1604 Try with this commit:
implementation 'com.github.pedroSG94.RootEncoder:library:fix~opengl-start-SNAPSHOT'
我对此进行了修复: #1604 尝试使用此提交:
implementation 'com.github.pedroSG94.RootEncoder:library:fix~opengl-start-SNAPSHOT'
I used this version but it still doesn't work. The following two pictures are new errors. Later, I no longer used the previous host activity. I changed an activity to display the OpenGlView on the floating window. Finally, it will not crash. I don't know why some phones crash on which activity. But I really appreciate your answer.
Hello,
Thank you for the report. It is interesting, the library is not able to get shaders resources. Please, help me to solve the error since I'm not able to reproduce it. I added a new commit that could resolve this error:
implementation 'com.github.pedroSG94.RootEncoder:library:f0b9aa3fcb'
Same error as before
Do you still have resources not found error like before?
I used it for nearly a year without any problems. Recently, the host app of the xposed hook seemed to have been hot-updated, which started to cause this problem on some models. After I changed the activity, it became normal. So I suggest you ignore this problem, because it is indeed a problem that only occurs with unconventional apps.
Hello,
I will ignore this issue until someone find a way to share a code example to reproduce the error. Marked as help wanted
package com.example.test;
import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.Button; import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.pedro.common.ConnectChecker; import com.pedro.encoder.input.sources.video.Camera2Source; import com.pedro.library.generic.GenericStream; import com.pedro.library.util.BitrateAdapter;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements ConnectChecker {
private SurfaceView surfaceView;
private Button btnStartStop;
private TextView tvStatus;
private final String streamUrl = "rtmp://localhost:1935/live/test";
private GenericStream genericStream;
private BitrateAdapter bitrateAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = findViewById(R.id.surfaceView);
btnStartStop = findViewById(R.id.btnStartStop);
tvStatus = findViewById(R.id.tvStatus);
genericStream = new GenericStream(this, this);
genericStream.changeVideoSource(new Camera2Source(this));
bitrateAdapter = new BitrateAdapter(bitrate -> genericStream.setVideoBitrateOnFly(bitrate));
bitrateAdapter.setMaxBitrate(1200_000 + 128_000); // video + audio max bitrate
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!genericStream.isOnPreview()) {
genericStream.startPreview(surfaceView);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
genericStream.getGlInterface().setPreviewResolution(width, height);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (genericStream.isOnPreview()) {
genericStream.stopPreview();
}
}
});
boolean prepared = genericStream.prepareVideo(640, 480, 1200_000, 0)
&& genericStream.prepareAudio(32000, true, 128_000);
if (!prepared) {
tvStatus.setText("Failed to prepare stream");
btnStartStop.setEnabled(false);
return;
}
btnStartStop.setOnClickListener(v -> {
if (!genericStream.isStreaming()) {
genericStream.startStream(streamUrl);
btnStartStop.setText("Stop Stream");
tvStatus.setText("Connecting...");
} else {
genericStream.stopStream();
btnStartStop.setText("Start Stream");
tvStatus.setText("Stream stopped");
}
});
}
@Override
public void onConnectionStarted(String url) {
runOnUiThread(() -> tvStatus.setText("Connection started"));
}
@Override
public void onConnectionSuccess() {
runOnUiThread(() -> tvStatus.setText("Connected"));
}
@Override
public void onConnectionFailed(String reason) {
runOnUiThread(() -> {
tvStatus.setText("Connection failed: " + reason);
btnStartStop.setText("Start Stream");
});
if (genericStream.getStreamClient().reTry(5000, reason, null)) {
runOnUiThread(() -> tvStatus.setText("Retrying..."));
} else {
genericStream.stopStream();
}
}
@Override
public void onNewBitrate(long bitrate) {
final float mbps = bitrate / 1_000_000f;
runOnUiThread(() -> tvStatus.setText(String.format(Locale.getDefault(), "Bitrate: %.2f Mbps", mbps)));
bitrateAdapter.adaptBitrate(bitrate, genericStream.getStreamClient().hasCongestion());
}
@Override
public void onDisconnect() {
runOnUiThread(() -> {
tvStatus.setText("Disconnected");
btnStartStop.setText("Start Stream");
});
}
@Override
public void onAuthError() {
runOnUiThread(() -> {
tvStatus.setText("Auth error");
btnStartStop.setText("Start Stream");
});
genericStream.stopStream();
}
@Override
public void onAuthSuccess() {
runOnUiThread(() -> tvStatus.setText("Auth success"));
}
@Override
protected void onDestroy() {
super.onDestroy();
genericStream.release();
}
}
Process: com.example.test, PID: 10775 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: java.lang.NullPointerException: getSurfaceTexture(...) must not be null at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3762) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3929) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2284) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:210) at android.os.Looper.loop(Looper.java:299) at android.app.ActivityThread.main(ActivityThread.java:8302) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1037) Caused by: java.lang.NullPointerException: getSurfaceTexture(...) must not be null at com.pedro.encoder.input.gl.render.MainRender.getSurfaceTexture(MainRender.kt:182) at com.pedro.library.view.GlStreamInterface.getSurfaceTexture(GlStreamInterface.kt:136) at com.pedro.library.base.StreamBase.changeVideoSource(StreamBase.kt:390) at com.example.test.MainActivity.onCreate(MainActivity.java:39) at android.app.Activity.performCreate(Activity.java:8191) at android.app.Activity.performCreate(Activity.java:8159) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1330) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3735) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3929) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2284)
Hello,
Thank you for the report, it is a bug introduced in the last release. For now you can do this that is equivalent and works. Replace this:
genericStream = new GenericStream(this, this);
genericStream.changeVideoSource(new Camera2Source(this));
To:
genericStream = new GenericStream(this, this, new Camera2Source(context), new MicrophoneSource());
//GenericStream class use Camera2Source and MicrophoneSource by default so the above line is equivalent to
genericStream = new GenericStream(this, this)
Fixed in the last commit: https://github.com/pedroSG94/RootEncoder/commit/a630ee4d79c64b8ce544da17062b6ea317ca6b1b
hello sir. i am doing a project based on this library. i am almost done. i only have two issues remaining. video streaming on and off. just audio will stream when video is off and show a black screen (optional) and one more is skin (face) smoothening filter. can you please help me here?
public void toggleCamera(){
if(isCameraOn){
isCameraOn = false;
//these lines are declared above
// VideoSource videoSource = genericStream.getVideoSource();
// if (videoSource instanceof Camera2Source ) {
// source = (Camera2Source)videoSource;
// source.enableAutoWhiteBalance(CameraCharacteristics.CONTROL_AWB_MODE_DAYLIGHT);
// source.enableAutoExposure();
// if(source.getCameraFacing() == Facing.BACK){
// source.switchCamera();
// }
// }
source.stop();
}else {
isCameraOn = true;
source.start(surfaceView.getSurfaceTexture());//java.lang.NullPointerException: getSurfaceTexture(...) must not be null
source.start(genericStream.getSurfaceTexture());//IllegalStateException: getSurfaceTexture only available with VideoManager.Source.DISABLED
}
}
i am stuck here. also a little advice for the filter maybe. for your information, my whole code is written above. i am using GenericStream.
Hello,
The first one you have 2 ways:
- Using muteVideo /unmuteVideo method like this:
genericStream.getGlInterface().muteVideo()
- Using BlackFilterRender:
genericStream.getGlInterface().addFilter(BlackFilterRender())
For the skin filter you have the beauty filter:
genericStream.getGlInterface().addFilter(BeautyFilterRender())
thank you very much sir. you saved my day.