我在将 Vidyo 集成到现有应用程序时遇到问题。视频聊天 lanches、连接和工作得很好。我遇到的问题是在关闭 Vidyo 活动之后。前一个活动返回,通过 OnResume() 继续执行,并正常运行。任何用户输入后,应用程序都会重新启动而不会发生任何崩溃。这是日志中唯一的错误。
> E: Bluetooth binder is null E: Failed to open libwvm.so: dlopen
> failed: library "libwvm.so" not found E: glUtilsParamSize: unknow
> param 0x000082da E: glUtilsParamSize: unknow param 0x000082da E:
> glUtilsParamSize: unknow param 0x000082da E: glUtilsParamSize: unknow
> param 0x000082da E: Bluetooth binder is null E:
> [ERROR:interface_registry.cc(104)] Failed to locate a binder for
> interface: autofill::mojom::PasswordManagerDriver E:
> validate_display:99 error 3008 (EGL_BAD_DISPLAY)
> [ 02-26 15:46:22.399 14354:14521 D/ ] HostConnection::get() New Host Connection established 0x6d386280, tid
> 14521
主要是:
E: validate_display:99 错误 3008 (EGL_BAD_DISPLAY)
这是我的基本 Vidyo 活动
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Vibrator;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ToggleButton;
import com.example.android.multidex.myapplication.R;
import com.vidyo.VidyoClient.Connector.Connector;
import com.vidyo.VidyoClient.Connector.ConnectorPkg;
import com.vidyo.VidyoClient.Device.RemoteCamera;
import com.vidyo.VidyoClient.Endpoint.LogRecord;
import com.vidyo.VidyoClient.Endpoint.Participant;
import com.vidyo.VidyoClient.NetworkInterface;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Request;
import okhttp3.Response;
public class Vidyo extends Activity implements VI, View.OnClickListener, Connector.IConnect, Connector.IRegisterLogEventListener, Connector.IRegisterNetworkInterfaceEventListener {
private VidyoConnectorState mVidyoConnectorState = VidyoConnectorState.VidyoConnectorStateDisconnected;
private boolean mVidyoClientInitialized = false;
private Connector mVidyoConnector = null;
private ToggleButton cameraSwitch, privacySwitch, microphoneSwitch;
private LinearLayout toolbar;
private FrameLayout videoFrame;
private String resource = null;
private ServiceConnection SC;
private boolean isBound = false;
private RadioService RS;
enum VidyoConnectorState {
VidyoConnectorStateConnected,
VidyoConnectorStateDisconnected,
VidyoConnectorStateDisconnectedUnexpected,
VidyoConnectorStateFailure;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.vidyo);
resource = getIntent().getStringExtra("resource");
videoFrame = findViewById(R.id.videoFrame);
cameraSwitch = findViewById(R.id.cameraSwitch);
privacySwitch = findViewById(R.id.privacySwitch);
microphoneSwitch = findViewById(R.id.microphoneSwitch);
toolbar = findViewById(R.id.toolbar);
ConnectorPkg.setApplicationUIContext(this);
mVidyoClientInitialized = ConnectorPkg.initialize();
microphoneSwitch.setOnClickListener(this);
privacySwitch.setOnClickListener(this);
cameraSwitch.setOnClickListener(this);
}
@Override
public void onClick(View view) {
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(10);
switch (view.getId()) {
case R.id.microphoneSwitch:
mVidyoConnector.setMicrophonePrivacy(microphoneSwitch.isChecked());
break;
case R.id.privacySwitch:
mVidyoConnector.setCameraPrivacy(privacySwitch.isChecked());
break;
case R.id.cameraSwitch:
mVidyoConnector.cycleCamera();
break;
}
}
@Override
public void onStart() {
super.onStart();
SC = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
RadioService.LocalBinder binder = (RadioService.LocalBinder) service;
RS = binder.getService();
RS.vidyo_activity_callbacks(Vidyo.this);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
isBound = bindService(new Intent(this, RadioService.class), SC, BIND_IMPORTANT);
if (mVidyoConnector != null) {
mVidyoConnector.setMode(Connector.ConnectorMode.VIDYO_CONNECTORMODE_Foreground);
}
}
@Override
public void onResume() {
super.onResume();
ViewTreeObserver viewTreeObserver = videoFrame.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
videoFrame.getViewTreeObserver().removeOnGlobalLayoutListener(this);
if (mVidyoConnector == null) {
if (mVidyoClientInitialized) {
try {
mVidyoConnector = new Connector(videoFrame, Connector.ConnectorViewStyle.VIDYO_CONNECTORVIEWSTYLE_Default, 50, "info@VidyoClient info@VidyoConnector warning", "", 0);
// Set initial position
refreshUI();
connect();
} catch (Exception e) {
LOG.e("VidyoConnector Construction failed", e.getMessage());
}
} else {
LOG.e("ERROR: VidyoClientInitialize failed - not constructing VidyoConnector ...");
}
LOG.i("onResume: mVidyoConnectorConstructed => " + (mVidyoConnector != null ? "success" : "failed"));
}
}
});
}
}
private void connect(){
final String data = Jwts.builder()
.setHeader(RadioService.header)
.claim("userId", RadioService.user.getUser_id())
.claim("handle", RadioService.user.getHandle())
.claim("room", "nineteen")
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 60000))
.signWith(SignatureAlgorithm.HS256, RadioService.user.getKey())
.compact();
Request request = new Request.Builder()
.url(RadioService.SITE_URL + "server/generate_token.php")
.post(new FormBody.Builder().add("data", data).build())
.build();
RadioService.client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
LOG.e("onFailure", e.getMessage());
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.isSuccessful()) {
try {
String data = response.body().string();
LOG.i(RadioService.SITE_URL + "server/generate_token.php", data);
final JSONObject object = new JSONObject(data);
runOnUiThread(new Runnable() {
@Override
public void run() {
final boolean status;
try {
status = mVidyoConnector.connect(object.getString("host"), object.getString("token"), object.getString("handle"), resource, Vidyo.this);
LOG.i("Connected " + status);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
} catch (JSONException e) {
LOG.e("JSONException", e.getMessage());
}
}
}
});
}
@Override
public void onStop() {
if (RS != null) RS.vidyo_activity_callbacks(null);
if (isBound) unbindService(SC);
RS = null;
if (mVidyoConnector != null) {
mVidyoConnector.setMode(Connector.ConnectorMode.VIDYO_CONNECTORMODE_Background);
}
super.onStop();
}
@Override
public void onDestroy() {
LOG.i("ONDESTROY");
// Release device resources
if (mVidyoConnector != null) {
mVidyoConnector.disconnect();
mVidyoConnector.disable();
mVidyoConnector = null;
}
// Uninitialize the VidyoClient library
ConnectorPkg.uninitialize();
super.onDestroy();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Refresh the video size after it is painted
ViewTreeObserver viewTreeObserver = videoFrame.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
videoFrame.getViewTreeObserver().removeOnGlobalLayoutListener(this);
refreshUI();
}
});
}
}
private void refreshUI() {
mVidyoConnector.showViewAt(videoFrame, 0, 0, videoFrame.getWidth(), videoFrame.getHeight());
}
private void connectorStateUpdated(VidyoConnectorState state, final String statusText) {
LOG.i("connectorStateUpdated, state = " + state.toString());
mVidyoConnectorState = state;
// Execute this code on the main thread since it is updating the UI layout
runOnUiThread(new Runnable() {
@Override
public void run() {
// Set the status text in the toolbar
LOG.i("TEXTVIEW SHOULD SHOW", statusText);
Toaster.toastlow(Vidyo.this, statusText);
if (mVidyoConnectorState == VidyoConnectorState.VidyoConnectorStateConnected) {
//toolbar.setVisibility(View.INVISIBLE);
} else {
//TODO: reconnect
}
}
});
}
@Override
public void onSuccess() {
connectorStateUpdated(VidyoConnectorState.VidyoConnectorStateConnected, "Connected");
}
@Override
public void onFailure(Connector.ConnectorFailReason reason) {
LOG.i("onFailure: connection attempt failed, reason = " + reason.toString());
connectorStateUpdated(VidyoConnectorState.VidyoConnectorStateFailure, "Connection failed");
}
@Override
public void onDisconnected(Connector.ConnectorDisconnectReason reason) {
if (reason == Connector.ConnectorDisconnectReason.VIDYO_CONNECTORDISCONNECTREASON_Disconnected) {
LOG.i("onDisconnected: successfully disconnected, reason = " + reason.toString());
connectorStateUpdated(VidyoConnectorState.VidyoConnectorStateDisconnected, "Disconnected");
} else {
LOG.i("onDisconnected: unexpected disconnection, reason = " + reason.toString());
connectorStateUpdated(VidyoConnectorState.VidyoConnectorStateDisconnectedUnexpected, "Unexpected disconnection");
}
}
@Override
public void onLog(LogRecord logRecord) {
LOG.i(logRecord.name + " : " + logRecord.level + " : " + logRecord.functionName + " : " + logRecord.message);
}
@Override
public void onNetworkInterfaceAdded(NetworkInterface vidyoNetworkInterface) {
LOG.i("onNetworkInterfaceAdded: name=" + vidyoNetworkInterface.getName() + " address=" + vidyoNetworkInterface.getAddress() + " type=" + vidyoNetworkInterface.getType() + " family=" + vidyoNetworkInterface.getFamily());
}
@Override
public void onNetworkInterfaceRemoved(NetworkInterface vidyoNetworkInterface) {
LOG.i("onNetworkInterfaceRemoved: name=" + vidyoNetworkInterface.getName() + " address=" + vidyoNetworkInterface.getAddress() + " type=" + vidyoNetworkInterface.getType() + " family=" + vidyoNetworkInterface.getFamily());
}
@Override
public void onNetworkInterfaceSelected(NetworkInterface vidyoNetworkInterface, NetworkInterface.NetworkInterfaceTransportType vidyoNetworkInterfaceTransportType) {
LOG.i("onNetworkInterfaceSelected: name=" + vidyoNetworkInterface.getName() + " address=" + vidyoNetworkInterface.getAddress() + " type=" + vidyoNetworkInterface.getType() + " family=" + vidyoNetworkInterface.getFamily());
}
@Override
public void onNetworkInterfaceStateUpdated(NetworkInterface vidyoNetworkInterface, NetworkInterface.NetworkInterfaceState vidyoNetworkInterfaceState) {
LOG.i("onNetworkInterfaceStateUpdated: name=" + vidyoNetworkInterface.getName() + " address=" + vidyoNetworkInterface.getAddress() + " type=" + vidyoNetworkInterface.getType() + " family=" + vidyoNetworkInterface.getFamily() + " state=" + vidyoNetworkInterfaceState);
}
}
这是一个多活动应用程序,除 Vidyo 活动外,没有其他活动会在返回主活动时创建重新启动应用程序的行为。我没有发现任何与 Vidyo 活动特别不同的东西会导致这种行为。搜索指向 JavaScript 错误的错误点。
所以很明显我的问题是为什么应用程序会重新启动以及如何修复它?