iOS

# 实现插件特性

本文展示如何实现菊风视频能力平台提供的插件功能。

# 前提条件

开始前,请确保你具备以下条件:

  • 已下载插件包

  • 已集成 Juphoon Plugin。目前只有该版本支持插件集成。

  • 插件 API说明在页面底部,请查看。

# Plugin进阶应用

# 1.定制化配置

/**
 * 设置定制化的配置参数
 *
 * @param customConfig 配置参数
 */
public void setCustomConfig(JCCRoomCustomConfig customConfig);

设置定制化配置参数详见 JCCRoomCustomConfig (opens new window)

/**
 * 定制化配置参数
 */
public class JCCGuestCustomConfig {
    /**
     * 通话页面配置
     */
   public void setTalkingConfig(JCCTalkingConfig talkingConfig) { }
}

# 通话页面配置

/**
 * 通话界面定制化配置参数
 */
public class JCCTalkingConfig {
    /**
     * 底部工具栏按钮枚举定义 JCCToolBarButtons
     */
    public enum JCCToolBarButtons {
        JCCEndButton,          // 挂断按钮
        JCCSpeakerButton,          // 扬声器按钮
        JCCMicButton,              // 麦克风按钮
        JCCCameraButton,           // 摄像头按钮
        JCCFlipButton,             // 翻转按钮
        JCCScreenShareButton,      // 屏幕共享按钮
        JCCChatButton,             // 文本消息按钮
        JCCLocalRecordButton,       // 本地录制按钮
        JCCCollaborationButton,   // 协作共享按钮
        JCCRemoteRecordButton     //远程录制
    }
    // 工具栏背景色
    public void setToolBarBackground(String toolBarBackground);
    // 顶部栏背景色
    public void setTopBarBackground(String topBarBackground);
    // 标题内容,默认显示通话中
    public void setTitle(String title);
    // JCToolbarButtons配置数组,默认4个按钮:JCCEndButton,JCCSpeakerButton,JCCMicButton,JCCCameraButton
    public void setToolBarButtons(JCCToolBarButtons[] toolBarButtons);
    //是否显示统计按钮,默认false
    public void setShowStatistic(boolean showStatistic);
    //是否显示最小化按钮,默认false
    public void setShowMinimized(boolean showMinimized);
    //自定义图层,需实现IBaseView协议,用来接收生命周期等事件,尺寸为全屏幕大小
    public void setCustomView(View customView);
    //是否使用第三方排队机,如果为true,则使用插件中排队机,默认为false
    public void setUseThirdACD(boolean useThirdACD);
    //是否显示签名取消按钮,默认false
    public void setShowCancelSign(boolean showCancelSign);
    //呼叫保持的音乐文件路径
    public void setHeldAudioPath(String heldAudioPath);
    //是否显示共享的画面,默认为true
    public boolean isShowShareCanvas();
    // 远端画笔颜色,默认#FFFF0000
    private String remotePaintColor = "#FFFF0000";
	public void setRemotePaintColor(String remotePaintColor);
    // 本端画笔颜色,默认#FF0E67FF
  	public void setLocalPaintColor(String localPaintColor);
    //电子签名是否全屏显示
    public void setSignFullScreen(boolean signFullScreen);
    //设置对讲模式小视频窗口显示宽度,单位 dp
    public void setPipSmallVideoWindowWidth(int pipSmallVideoWindowWidth);
    //设置对讲模式小视频窗口显示高度,单位 dp
    public void setPipSmallVideoWindowHeight(int pipSmallVideoWindowHeight);
    //设置演讲者模式小视频窗口显示宽度,单位 dp
    public void setSpeakSmallVideoWindowWidth(int speakSmallVideoWindowWidth);
    //设置演讲者模式小视频窗口显示高度,单位 dp
    public void setSpeakSmallVideoWindowHeight(int speakSmallVideoWindowHeight);
    // 全显示功能布局
    public void setFullDisplayFunctionLayout(boolean fullDisplayFunctionLayout);
    // 设置签名画笔大小
    public void setDefaultDoodleStrokeWidth(int defaultDoodleStrokeWidth);
    // 设置关闭摄像头后小窗口展示图片
    public void setVideoHoldSmallIcon(Bitmap videoHoldSmallIcon);
    // 设置关闭摄像头后大窗口展示图片
    public void setVideoHoldLargeIcon(Bitmap videoHoldLargeIcon);
    // 设置关闭摄像头后窗口背景色
    public void setVideoHoldBackgroundColor(String videoHoldBackgroundColor);
}
/**
 * 自定义图层实现IBaseView接口,可监听通话界面生命同期
 */
public interface IBaseView {
    /**
     * onCreate
     */
    void onCreate();
    /**
     * onStart
     */
    void onStart();
    /**
     * onResume
     */
    void onResume();
    /**
     * onStop
     */
    void onStop();
    /**
     * onPause
     */
    void onPause();
    /**
     * onDestroy
     */
    void onDestroy();
}

示例代码:

JCCGuestCustomConfig config = new JCCGuestCustomConfig();
JCCTalkingConfig talkingConfig = new JCCTalkingConfig();
...
  talkingConfig.setShowMinimized(true);
...
config.setTalkingConfig(talkingConfig);
GuestManager.getInstance().setCustomConfig(config);

# 2.如何通话页面中添加自定义视图

自定义图层需要实现 IBaseView 协议。

/**
 * 自定义图层实现IBaseView接口,可监听通话界面的生命周期
 */
public class CustomLayout extends RelativeLayout implements IBaseView {
    private Context mContext;

    public CustomLayout(Context context) {
        super(context);
        initLayout(context);
    }

    public CustomLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        initLayout(context);
    }

    public CustomLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initLayout(context);
    }

    private void initLayout(Context context) {
        this.mContext = context;
        View view = LayoutInflater.from(context).inflate(R.layout.custom_layout, this, true);
    }

    @Override
    public void onCreate() {

    }

    @Override
    public void onStart() {

    }

    @Override
    public void onResume() {

    }

    @Override
    public void onStop() {

    }

    @Override
    public void onPause() {

    }

    @Override
    public void onDestroy() {

    }
}

示例代码:

JCCRoomCustomConfig config = new JCCRoomCustomConfig();
JCCTalkingConfig talkingConfig = new JCCTalkingConfig();
CustomLayout customLayout = new CustomLayout(this);
talkingConfig.setCustomView(customLayout);
config.setTalkingConfig(talkingConfig);

# 3.开启国密

# 参数配置

开启国密需要在初始化的时候设置 JCCLoginParam (opens new window) 的 accountEntry 和 certificate 参数。

参数需要根据实际情况填写。

//帐户分录, 如果支持国密S3则需要设置certificate,否则不设置
String accountEntry = "AccountEntry:sarc -h arc@AccountEntry -p 198 -S 3;";
//S3国密密钥
String certificate = "";
//证书路径
File file = new File(Environment.getExternalStorageDirectory() + "/CA_gm_juphoon.der");
FileInputStream in = null;
	try {
		writeBytesToFile(getAssets().open("CA_gm_juphoon.der"), file);
		in = new FileInputStream(file);
        byte[] b = new byte[0];
        b = new byte[in.available()];
        int read = in.read(b);
        certificate = Base64.encodeToString(b, Base64.NO_WRAP);
	} catch (IOException e) {
		e.printStackTrace();
	}
JCCLoginParam loginParam = new JCCLoginParam();
loginParam.setCertificate(certificate);
loginParam.setAccountEntry(accountEntry);
loginParam.setServer("server");       //接入服务器的地址
loginParam.setAppKey("appKey");  //appKey
loginParam.setAppName("JCCGuest");//设置应用名
loginParam.setUserName("test"); //用户id
loginParam.setPassword("123456"); //用户密码
loginParam.setNickName("昵称"); //设置用户昵称
...
JCCRoomManager.getInstance().login(context, loginParam);

# 4.开启云加速

  1. 从管理平台申请加速云接入,并获得加速云接入地址,接口 key 和接入 key 密钥
  2. 登录参数中需要将上述获得的参数填入

# 接入地址

# 直连地址

一般是接入行方系统的外部地址。

# 加速云地址

公网 router ,用于提供公网上的 App 到直连地址连通质量。

// 测试参数

ListenerAccessKey ID: XuG4vjNLLpUEuo6qbVYvHMmr
ListenerAccessKey Secret: kB2RnoXi3iaxVkoUerL7ojd88BUNa0
加速云接入地址:Router:udp -h entry.jac.juphoon.com -p 4021 -ri -1;
直连地址:
udp:122.227.209.194:10122 (外网)
udp:192.168.3.200:10030(内网)

// 双接入地址
Router:udp -h entry.jac.juphoon.com -p 4021 -ri -1;udp -h 122.227.209.194 -p 10122 -ri -2;

# 地址格式

# 单地址格式1

协议:域名/ IP :端口

示例:

udp:122.227.209.194:10122

# 单地址格式2

Router:协议 -h 域名/IP -p 端口

示例:

Router:udp -h entry.jac.juphoon.com -p 4021

# 多地址

Router:单地址格式2;单地址格式2

示例:

Router:udp -h entry.jac.juphoon.com -p 4021 -ri -1;udp -h 122.227.209.194 -p 10122 -ri -2;

# 主备地址

Router:单地址格式2;单地址格式2 -bu

示例:

Router:udp -h entry.jac.juphoon.com -p 4021 -ri -1;udp -h 122.227.209.194 -p 10122 -ri -2 -bu;

示例代码:

JCCLoginParam loginParam = new JCCLoginParam();
...
loginParam.setServer("加速云接入地址");
loginParam.setAccelerateKey("加速云Key");
loginParam.setAccelerateKeySecret("加速云Key密钥");
...
JCCGuestManager.getInstance().login(context, loginParam);

# 5.如何在通话过程中弹窗

# Activity 方式

全透明 activity 添加弹框布局加载显示

/****** 在styles中申明activity的theme *******/
<style name="translucent">
	<item name="android:windowBackground">@color/translucent_background</item>
	<item name="android:windowIsTranslucent">true</item>
	<item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
</style>
    
/****** activity引用theme *******/
<activity
	android:name=".TestActivity"
	android:theme="@style/translucent"
	android:screenOrientation="portrait">
</activity>
    
/****** 继承Activity *******/  
public class TestActivity extends Activity
    
/****** 直接启动activity *******/
startActivity(new Intent(context, TestActivity.class));
/********** 设置自定义 view **********/
JCCRoomCustomConfig customConfig = new JCCRoomCustomConfig();
CustomView customview = new CustomView(this);
customConfig.getTalkingConfig().setCustomView(customview);
JCCRoomManager.getInstance().setCustomConfig(customConfig);

/********** 弹窗 **********/
View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popuplayout, null);
mPopWindow = new PopupWindow(contentView);
mPopWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
mPopWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
mPopWindow.showAtLocation(customview, 0, 0, 0);

# 悬浮窗方式

/********** Androidmanifest.xml 配置权限 **********/
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

/********** 请求权限 **********/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (!Settings.canDrawOverlays(this)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, 1000);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case 1000: {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (Settings.canDrawOverlays(this)) {
                    //若用户开启了overlay权限,则打开window
                    openWindow();
                } else {
                    Toast.makeText(this, "不开启overlay权限", Toast.LENGTH_SHORT).show();
                }
            }
            break;
        }
    }
}

/********** 弹窗 **********/
//获取WindowManager实例
final WindowManager windowManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);
//获取窗口布局参数实例
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
//设置窗口布局参数属性
params.width = 100;
params.height = 100;
//设置window的显示特性
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
//设置窗口类型
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
//获取窗口布局实例
Button button = new Button(this);
button.setText("测试弹窗");
//显示窗口
windowManager.addView(button, params);

# 6.点击事件拦截

需要拦截通话中按钮点击事件,需要实现 JCCRoomCallbackonViewEvent: 回调方法

/**
 * UI事件通知
 * @param viewEvent 事件类型
 * @return
 * - true  表示该事件由app外部处理,插件内部无需处理
 * - false 插件内部默认处理该事件
 */
boolean onViewEvent(@JCCConstants.JCCViewEvent int viewEvent);

示例代码

public boolean onViewEvent(int viewEvent) {
	if (viewEvent == JCCConstants.TALK_END_CLICK) {
		new Handler().postDelayed(()->{
			JCCRoomManager.getInstance().leave();
		},3 * 1000);
		return true;
	}
	return false;
}