I'm having an issue integrating Vidyo into an existing app. Video chat lanches, connects, and works just fine. The problem I'm running into is after closing the Vidyo activity. The previous activity returns, executes on through the OnResume(), and acts normal. Upon any user input the app restarts without any crash. Here is the only errors in log.
> 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
mainly:
E: validate_display:99 error 3008 (EGL_BAD_DISPLAY)
Here's my basic Vidyo activity
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);
}
}
It's a multiple activity application and no other activity creates this behavior of restarting the application when returning to the main activity except the Vidyo activity. I'm not seeing anything in particularly different with the Vidyo activity to cause this behavior. Searches for the error point towards a JavaScript error.
So obviously my question is why does the app restart and how to fix it?