3

我在将 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 错误的错误点。

所以很明显我的问题是为什么应用程序会重新启动以及如何修复它?

4

2 回答 2

0

我遇到了类似的问题。我不知道原因是否相同,但是在清单中将活动标记为 singleTop 为我修复了它。

于 2019-02-06T13:54:16.163 回答
0

我也遇到了同样的问题,但我通过检查 call off connector.disable() 方法解决了这个问题。

请关注 disconnect() API。它是在 onDisconencted() 回调之后的异步调用,因此如果您在活动退出之前触发它,这将导致崩溃,因为从 onDestroy() 您正在使用 disable() 释放客户端。

想象一下,您正在开始断开连接过程(这需要一些时间),同时释放所有资源/断开连接。

仅从用户交互角度(通过 UI 按钮)调用断开连接,并且一旦收到 onDisconnected() -> 在此处退出活动(完成),这将导致 onDestroy() 并释放客户端。同样,您可以通过 onBackPressed() 处理。

我希望它有所帮助。

于 2019-02-22T10:04:30.870 回答