Интеграция библиотеки Vidyo. Приложение перезапустится после выхода из видеочата

У меня проблема с интеграцией Vidyo в существующее приложение. Видеочат запускается, подключается и работает нормально. Проблема, с которой я сталкиваюсь, заключается в закрытии активности 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.

Поэтому, очевидно, мой вопрос: почему приложение перезагружается и как это исправить?


person Robert Goodrick    schedule 26.02.2018    source источник


Ответы (2)


Я столкнулся с похожей проблемой. Я не знаю, та же ли причина, но пометка активности как singleTop в манифесте исправила это для меня.

person Avezou    schedule 06.02.2019

Я также столкнулся с той же проблемой, но решил ее, проверив метод вызова connect.disable().

Пожалуйста, сосредоточьтесь на API разъединения(). Это асинхронный вызов, который следует за обратным вызовом onDisconencted(), поэтому, если вы активируете его прямо перед выходом из активности, это приведет к сбою, потому что из onDestroy() вы выпускаете клиента с помощью disable().

Представьте, что вы начинаете процесс отключения (который занимает некоторое время) и в то же время освобождаете все ресурсы/отбрасываете соединения.

Вызов для отключения только с точки зрения взаимодействия с пользователем (через кнопку пользовательского интерфейса) и после получения onDisconnected() -> выход из активности здесь (с завершением), что вызовет onDestroy() и освободит клиент. То же самое вы можете сделать с помощью onBackPressed().

Я надеюсь, что это помогает.

person Shivam Yadav    schedule 22.02.2019