OpenTok Android中的多个用户视频通话,在whatsapp上触摸时更改视频屏幕大小

时间:2018-06-18 09:25:54

标签: android video webrtc android-videoview opentok

我在android中使用opentok videocall库。我想要与WhatsApp相同的功能。在这个应用程序中,我的屏幕上有3个订阅者和1个发布者视图。当我们触摸任何订阅者视图时,它应该以全屏视图切换。我附加了一个屏幕,以便更好地理解。 当我们触摸订户2视图时,在此屏幕中,它应该与订户1交换其视图,当我们按任何其他订户视图时,它应该与大视图的主视图交换。

in this screen when we touch subscriber 2 it should exchange its screen with subscriber 1

屏幕二

enter image description here

屏幕三

enter image description here

我的代码在这里,我可以相互切换订阅者,但无法在主屏幕中管理它们。

清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tokbox.android.tutorials.simple_multiparty">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

我的activity_main.xml文件在这里

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
android:layout_width="match_parent" android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<RelativeLayout
    android:id="@+id/video_call_main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="visible"
    android:keepScreenOn="true">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"
        android:id="@+id/subscriberview0">

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="120dp"
        android:layout_height="150dp"
        android:layout_toLeftOf="@+id/subscriberview1"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:background="#154612"
        android:id="@+id/subscriberview2">
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="120dp"
        android:layout_height="150dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="10dp"
        android:layout_marginRight="5dp"
        android:background="#af1234"
        android:layout_toLeftOf="@+id/publisherview"
        android:id="@+id/subscriberview1">
    </RelativeLayout>

    <RelativeLayout
        android:background="#86dec6"
        android:id="@+id/publisherview"
        android:layout_height="150dp"
        android:layout_width="100dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="10dp"
        android:layout_marginRight="5dp">
    </RelativeLayout>
</RelativeLayout>

我的MainActivity.java文件在这里

package com.tokbox.android.tutorials.simple_multiparty;

import android.Manifest;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.opentok.android.BaseVideoRenderer;
import com.opentok.android.OpentokError;
import com.opentok.android.Publisher;
import com.opentok.android.PublisherKit;
import com.opentok.android.Session;
import com.opentok.android.Stream;
import com.opentok.android.Subscriber;
import com.opentok.android.TextureViewRenderer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.AppSettingsDialog;
import pub.devrel.easypermissions.EasyPermissions;

public class MainActivity extends AppCompatActivity
                      implements EasyPermissions.PermissionCallbacks,
                                 Publisher.PublisherListener,
                                 Session.SessionListener {

public static final String API_KEY = "46139802";//"46089252";
public static final String TOKEN = "T1==cGFydG5lcl9pZD00NjEzOTgwMiZzaWc9NjZmOGRiY2Q3MDdiNWNiY2M0Yzc4Nzg4NWZlYTZlNzdiYzQyZDRkZDpzZXNzaW9uX2lkPTFfTVg0ME5qRXpPVGd3TW41LU1UVXlPVE13TXpJME9UazNNbjVDWTFaUVpteG1NMnh2UTFocWVWUlBVazloVGxKM1NYUi1mZyZjcmVhdGVfdGltZT0xNTI5MzAzMzQxJm5vbmNlPTAuNDEyNTM2NjMyNDUxODU2MjMmcm9sZT1wdWJsaXNoZXImZXhwaXJlX3RpbWU9MTUyOTM4OTcwMSZpbml0aWFsX2xheW91dF9jbGFzc19saXN0PQ==";
public static final String SESSION_ID = "1_MX40NjEzOTgwMn5-MTUyOTMwMzI0OTk3Mn5CY1ZQZmxmM2xvQ1hqeVRPUk9hTlJ3SXR-fg";

private static final String TAG = "simple-multiparty " + MainActivity.class.getSimpleName();

private final int MAX_NUM_SUBSCRIBERS = 4;

private static final int RC_SETTINGS_SCREEN_PERM = 123;
private static final int RC_VIDEO_APP_PERM = 124;

private Session mSession;
private Publisher mPublisher;

private ArrayList<Subscriber> mSubscribers = new ArrayList<Subscriber>();
private HashMap<Stream, Subscriber> mSubscriberStreams = new HashMap<Stream, Subscriber>();

private RelativeLayout mPublisherViewContainer;
private RelativeLayout subscriberview0, subscriberview1, subscriberview2;
int widthView;
RelativeLayout.LayoutParams  view0Params, view1Params, view2Params, viewParams;

View subscriberViewBig;
View subscriberViewSmall;

@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.d(TAG, "onCreate");

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mPublisherViewContainer = (RelativeLayout) findViewById(R.id.publisherview);
    subscriberview0 = (RelativeLayout) findViewById(R.id.subscriberview0);
    subscriberview1 = (RelativeLayout) findViewById(R.id.subscriberview1);
    subscriberview2 = (RelativeLayout) findViewById(R.id.subscriberview2);

    int totalMeasuredwidth = 0;
    int Measuredheight = 0;
    Point size = new Point();
    WindowManager w = getWindowManager();

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)    {
        w.getDefaultDisplay().getSize(size);
        totalMeasuredwidth = size.x;
        Measuredheight = size.y;
    }else{
        Display d = w.getDefaultDisplay();
        totalMeasuredwidth = d.getWidth();
        Measuredheight = d.getHeight();
    }

    int paddingInPx = (int) convertDpToPixel(5, MainActivity.this);
    totalMeasuredwidth = totalMeasuredwidth - (4*paddingInPx);

    widthView = totalMeasuredwidth / 3 ;
    Log.d(TAG, "widthView : in pixel "+ widthView);


    view0Params = new RelativeLayout.LayoutParams(widthView, (int) convertDpToPixel(150, MainActivity.this));
    view1Params = new RelativeLayout.LayoutParams(widthView, (int) convertDpToPixel(150, MainActivity.this));
    view2Params = new RelativeLayout.LayoutParams(widthView, (int) convertDpToPixel(150, MainActivity.this));
    viewParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);

    requestPermissions();

    subscriberview0.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mPublisherViewContainer.bringToFront();
            subscriberview0.setLayoutParams(viewParams);

            view1Params.rightMargin = (int) Utility.convertDpToPixel(5, MainActivity.this);
            view1Params.bottomMargin = (int) Utility.convertDpToPixel(10, MainActivity.this);
            view1Params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            view1Params.addRule(RelativeLayout.LEFT_OF, R.id.publisherview);
            subscriberview1.setLayoutParams(view1Params);
            subscriberview1.bringToFront();

            view2Params.rightMargin = (int) Utility.convertDpToPixel(5, MainActivity.this);
            view2Params.bottomMargin = (int) Utility.convertDpToPixel(10, MainActivity.this);
            view2Params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            view2Params.addRule(RelativeLayout.LEFT_OF, R.id.subscriberview1);
            subscriberview2.setLayoutParams(view2Params);
            subscriberview2.bringToFront();
        }
    });

    subscriberview1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mPublisherViewContainer.bringToFront();

            view0Params.rightMargin = (int) Utility.convertDpToPixel(5, MainActivity.this);
            view0Params.bottomMargin = (int) Utility.convertDpToPixel(10, MainActivity.this);
            view0Params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            view0Params.addRule(RelativeLayout.LEFT_OF, R.id.publisherview);
            subscriberview0.setLayoutParams(view0Params);
            subscriberview0.bringToFront();

            viewParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
            subscriberview1.setLayoutParams(viewParams);

            view2Params.rightMargin = (int) Utility.convertDpToPixel(5, MainActivity.this);
            view2Params.bottomMargin = (int) Utility.convertDpToPixel(10, MainActivity.this);
            view2Params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            view2Params.addRule(RelativeLayout.LEFT_OF, R.id.subscriberview0);
            subscriberview2.setLayoutParams(view2Params);
            subscriberview2.bringToFront();
        }
    });

    subscriberview2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mPublisherViewContainer.bringToFront();

            view0Params.rightMargin = (int) Utility.convertDpToPixel(3, MainActivity.this);
            view0Params.bottomMargin = (int) Utility.convertDpToPixel(10, MainActivity.this);
            view0Params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            view0Params.addRule(RelativeLayout.LEFT_OF, R.id.publisherview);
            subscriberview0.setLayoutParams(view0Params);
            subscriberview0.bringToFront();

            view1Params.rightMargin = (int) Utility.convertDpToPixel(5, MainActivity.this);
            view1Params.bottomMargin = (int) Utility.convertDpToPixel(10, MainActivity.this);
            view1Params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            view1Params.addRule(RelativeLayout.LEFT_OF, R.id.subscriberview0);
            subscriberview1.setLayoutParams(view1Params);
            subscriberview1.bringToFront();

            subscriberview2.setLayoutParams(viewParams);
        }
    });
}

private int getResIdForSubscriberIndex(int index) {
    TypedArray arr = getResources().obtainTypedArray(R.array.subscriber_view_ids);
    int subId = arr.getResourceId(index, 0);
    arr.recycle();
    return subId;
}

public static float convertDpToPixel(float dp, Context context){
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    return px;
}

@Override
protected void onStart() {
    Log.d(TAG, "onStart");

    super.onStart();
}

@Override
protected void onRestart() {
    Log.d(TAG, "onRestart");

    super.onRestart();
}

@Override
protected void onResume() {
    Log.d(TAG, "onResume");

    super.onResume();

    if (mSession == null) {
        return;
    }
    mSession.onResume();
}

@Override
protected void onPause() {
    Log.d(TAG, "onPause");

    super.onPause();

    if (mSession == null) {
        return;
    }
    mSession.onPause();

    if (isFinishing()) {
        disconnectSession();
    }
}

@Override
protected void onStop() {
    Log.d(TAG, "onPause");

    super.onStop();
}

@Override
protected void onDestroy() {
    Log.d(TAG, "onDestroy");

    disconnectSession();

    super.onDestroy();
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

@Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
    Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
}

@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
    Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());

    if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
        new AppSettingsDialog.Builder(this)
                .setTitle(getString(R.string.title_settings_dialog))
                .setRationale(getString(R.string.rationale_ask_again))
                .setPositiveButton(getString(R.string.setting))
                .setNegativeButton(getString(R.string.cancel))
                .setRequestCode(RC_SETTINGS_SCREEN_PERM)
                .build()
                .show();
    }
}

@AfterPermissionGranted(RC_VIDEO_APP_PERM)
private void requestPermissions() {
    String[] perms = {
            Manifest.permission.INTERNET,
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
    };
    if (EasyPermissions.hasPermissions(this, perms)) {
        //mSession = new Session.Builder(MainActivity.this, OpenTokConfig.API_KEY, OpenTokConfig.SESSION_ID).build();
        mSession = new Session.Builder(MainActivity.this, API_KEY, SESSION_ID)
                .sessionOptions(new Session.SessionOptions() {
                    @Override
                    public boolean useTextureViews() {
                        return true;
                    }
                }).build();
        mSession.setSessionListener(this);
        mSession.connect(TOKEN);
    } else {
        EasyPermissions.requestPermissions(this, getString(R.string.rationale_video_app), RC_VIDEO_APP_PERM, perms);
    }
}
@Override
public void onConnected(Session session) {
    Log.d(TAG, "onConnected: Connected to session " + session.getSessionId());

    mPublisher = new Publisher.Builder(MainActivity.this).name("publisher").build();

    mPublisher.setPublisherListener(this);
    mPublisher.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL);

    mPublisherViewContainer.addView(mPublisher.getView());

    mSession.publish(mPublisher);
}

@Override
public void onDisconnected(Session session) {
    Log.d(TAG, "onDisconnected: disconnected from session " + session.getSessionId());

    mSession = null;
}

@Override
public void onError(Session session, OpentokError opentokError) {
    Log.d(TAG, "onError: Error (" + opentokError.getMessage() + ") in session " + session.getSessionId());

    Toast.makeText(this, "Session error. See the logcat please.", Toast.LENGTH_LONG).show();
    finish();
}

@Override
public void onStreamReceived(Session session, Stream stream) {
    Log.d(TAG, "onStreamReceived: New stream " + stream.getStreamId() + " in session " + session.getSessionId());

    if (mSubscribers.size() + 1 > MAX_NUM_SUBSCRIBERS) {
        Toast.makeText(this, "New subscriber ignored. MAX_NUM_SUBSCRIBERS limit reached.", Toast.LENGTH_LONG).show();
        return;
    }

    final Subscriber subscriber = new Subscriber.Builder(MainActivity.this, stream).build();
    mSession.subscribe(subscriber);
    mSubscribers.add(subscriber);
    mSubscriberStreams.put(stream, subscriber);

    subscriber.setSubscribeToAudio(false);

    int position = mSubscribers.size() - 1;
    int id = getResources().getIdentifier("subscriberview" + (new Integer(position)).toString(), "id", MainActivity.this.getPackageName());
    RelativeLayout subscriberViewContainer = (RelativeLayout) findViewById(id);

    //subscriber.setStyle(BaseVideoRenderer.STYLE_VIDEO_FILL, BaseVideoRenderer.STYLE_VIDEO_FILL);
    subscriber.setStyle(TextureViewRenderer.STYLE_VIDEO_SCALE, TextureViewRenderer.STYLE_VIDEO_FIT);
    subscriberViewContainer.addView(subscriber.getView());

    if (mSubscribers.size() == 1) {
        Log.d(TAG, "mSubscribers: view0 visible size : " + mSubscribers.size());
        subscriberview1.setVisibility(View.GONE);
        subscriberview2.setVisibility(View.GONE);
    }

    if (mSubscribers.size() == 2) {
        Log.d(TAG, "mSubscribers: view1 visible size : " + mSubscribers.size());
        subscriberview1.setVisibility(View.VISIBLE);
        subscriberview2.setVisibility(View.GONE);

        view1Params.rightMargin = (int) Utility.convertDpToPixel(5, MainActivity.this);
        view1Params.bottomMargin = (int) Utility.convertDpToPixel(10, MainActivity.this);
        view1Params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        view1Params.addRule(RelativeLayout.LEFT_OF, R.id.publisherview);
        subscriberview1.setLayoutParams(view1Params);
        //subscriberview1.setZ(1);
        subscriberview1.bringToFront();
    }

    if (mSubscribers.size() == 3) {
        Log.d(TAG, "mSubscribers: view2 visible size : " + mSubscribers.size());
        subscriberview1.setVisibility(View.VISIBLE);
        subscriberview2.setVisibility(View.VISIBLE);

        view2Params.rightMargin = (int) Utility.convertDpToPixel(5, MainActivity.this);
        view2Params.bottomMargin = (int) Utility.convertDpToPixel(10, MainActivity.this);
        view2Params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        view2Params.addRule(RelativeLayout.LEFT_OF, R.id.subscriberview1);
        subscriberview2.setLayoutParams(view2Params);
        //subscriberview1.setZ(1);
        subscriberview2.bringToFront();
    }
}

@Override
public void onStreamDropped(Session session, Stream stream) {
    Log.d(TAG, "onStreamDropped: Stream " + stream.getStreamId() + " dropped from session " + session.getSessionId());

    Subscriber subscriber = mSubscriberStreams.get(stream);
    if (subscriber == null) {
        return;
    }

    int position = mSubscribers.indexOf(subscriber);
    int id = getResources().getIdentifier("subscriberview" + (new Integer(position)).toString(), "id", MainActivity.this.getPackageName());

    mSubscribers.remove(subscriber);
    mSubscriberStreams.remove(stream);

    RelativeLayout subscriberViewContainer = (RelativeLayout) findViewById(id);
    subscriberViewContainer.removeView(subscriber.getView());
}

@Override
public void onStreamCreated(PublisherKit publisherKit, Stream stream) {
    Log.d(TAG, "onStreamCreated: Own stream " + stream.getStreamId() + " created");
}

@Override
public void onStreamDestroyed(PublisherKit publisherKit, Stream stream) {
    Log.d(TAG, "onStreamDestroyed: Own stream " + stream.getStreamId() + " destroyed");
}

@Override
public void onError(PublisherKit publisherKit, OpentokError opentokError) {
    Log.d(TAG, "onError: Error (" + opentokError.getMessage() + ") in publisher");

    Toast.makeText(this, "Session error. See the logcat please.", Toast.LENGTH_LONG).show();
    finish();
}

private void disconnectSession() {
    if (mSession == null) {
        return;
    }

    if (mSubscribers.size() > 0) {
        for (Subscriber subscriber : mSubscribers) {
            if (subscriber != null) {
                mSession.unsubscribe(subscriber);
                subscriber.destroy();
            }
        }
    }

    if (mPublisher != null) {
        mPublisherViewContainer.removeView(mPublisher.getView());
        mSession.unpublish(mPublisher);
        mPublisher.destroy();
        mPublisher = null;
    }
    mSession.disconnect();
 }
}

我的实用程序文件在这里

package com.tokbox.android.tutorials.simple_multiparty;
import android.content.Context;
import android.content.res.Resources;
import android.util.DisplayMetrics;
public class Utility {
public static float convertDpToPixel(float dp, Context context){
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * ((float)metrics.densityDpi / 
   DisplayMetrics.DENSITY_DEFAULT);
    return px;
}
}

1 个答案:

答案 0 :(得分:1)

Tokbox QA这里的东西。

Opentok不会为您做到这一点,因为那是您的功能。您需要捕获屏幕按下,并自行调整发布者/订阅者的画布大小。我们不会处理您希望如何在屏幕上显示订阅者。