为年迈母亲打造的“亲情关怀”视频聊天软件

news2024/11/19 5:51:36

写在前面

母亲的眼神越来越不好了,长期干农活的手也愈加粗糙,智能手机本是一个平常之物,她确无缘使用,现在仍在不断更换着“翻盖手机”。为了能让她绕开微信视频聊天那些繁琐而容易点错的功能,程序员的我“开发”下面一个聊天软件。
妈妈的翻盖手机
视频聊天
一键拨号

技术探索

本来一开始是准备直接0基础开始写代码的,转了一圈发现难度太大,又想到直接找现成的解决方案,结果下载了一堆app,都是各种广告弹窗,最后发现zego的一些开眼sdk基本可以满足,就花了一天时间进行“改造”。
主要改造的方向是:

(1)去掉app上的各种账号设置
(2)从首页直接进入聊天页面,不需要加好友啥的复杂功能
(3)字体字号足够大

最后

经过一天的改造,已经基本完成所需要的核心功能,但是还有许多问题

(1)聊天无法直接通过app拉起,需要两人同时上线才可以
(2)同时只能我和妈妈两个人聊天
(3)聊天的主画面是反的(本人是大窗显示,对方是小窗显示)
(4)挂断电话是app无法直接退出。

代码

这里我把核心代码写出来,如有大神可以帮忙完善我的1.0版本

MainAdapter.java

package im.zego.expresssample.adapter;

import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;


import im.zego.expresssample.R;
import im.zego.expresssample.entity.ModuleInfo;

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

/**
 * Created by zego on 2018/2/6.
 */

public class MainAdapter extends RecyclerView.Adapter {

    private List<ModuleInfo> topicList = new ArrayList<>();
    private OnItemClickListener mOnItemClickListener;

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.module_list, parent, false);
        return new MyViewHolder(v);
    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
        final MyViewHolder myViewHolder = (MyViewHolder) holder;
        if (mOnItemClickListener != null) {
            myViewHolder.list.setOnClickListener(v -> {
                if (mOnItemClickListener != null) {
                    int position1 = myViewHolder.getLayoutPosition();
                    v.setTag(topicList.get(position1));
                    mOnItemClickListener.onItemClick(v, position1);
                }
            });
        }
        ModuleInfo moduleInfo = topicList.get(position);
        if (moduleInfo.getTitleName() != null) {
            myViewHolder.title.setVisibility(View.VISIBLE);
        } else {
            myViewHolder.title.setVisibility(View.GONE);
        }

        myViewHolder.name.setText(moduleInfo.getModule());
    }

    @Override
    public int getItemCount() {
        return topicList.size();
    }

    /**
     * 新增模块信息
     *
     * @param moduleInfo module info
     */
    public void addModuleInfo(ModuleInfo moduleInfo) {
        topicList.add(moduleInfo);
        notifyDataSetChanged();
    }

    public void clear() {
        topicList.clear();
    }

    public static class MyViewHolder extends RecyclerView.ViewHolder {
        RelativeLayout list;
        TextView name;
        RelativeLayout title;

        MyViewHolder(View itemView) {
            super(itemView);
            list = itemView.findViewById(R.id.list);
            name = itemView.findViewById(R.id.name);
            title = itemView.findViewById(R.id.title);
        }
    }

    public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
        this.mOnItemClickListener = mOnItemClickListener;
    }

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }
}


MainActivity.java

package im.zego.expresssample.ui;

import android.content.Intent;
import android.content.pm.PackageManager;

import android.os.Build;
import android.os.Bundle;

import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;


import im.zego.debugandconfig.SettingActivity;
import im.zego.others.camera.CameraActivity;
import im.zego.others.effectsbeauty.EffectsBeautyActivity;
import im.zego.others.multivideosource.MultiVideoSourceActivity;
import im.zego.others.screensharing.ScreenSharingActivity;
import im.zego.others.beautyandwatermarkandsnapshot.BeautyWatermarkSnapshotActivity;
import im.zego.others.flowcontrol.FlowControlActivity;
import im.zego.others.mediaplayer.UI.MediaPlayerSelectionActivity;
import im.zego.others.multiplerooms.MultipleRoomsActivity;
import im.zego.others.networkandperformance.NetworkAndPerformanceActivity;
import im.zego.others.recording.RecordingActivity;
import im.zego.others.security.SecurityActivity;
import im.zego.others.sei.SEIActivity;
import im.zego.others.streammixing.MixerMainActivity;
import im.zego.others.superresolution.SuperResolutionActivity;

import im.zego.CustomerVideoCapture.CustomerVideoCaptureActivity;
import im.zego.Scenes.VideoForMultipleUsers.VideoForMultipleUsersLogin;
import im.zego.advancedaudioprocessing.audio3a.Audio3aActivity;
import im.zego.advancedaudioprocessing.audioeffectplayer.AudioEffectPlayerActivity;
import im.zego.advancedaudioprocessing.customaudiocaptureandrendering.CustomAudioCaptureAndRenderingLoginActivity;
import im.zego.advancedaudioprocessing.earreturnandchannelsettings.EarReturnandChannelSettingsActivity;
import im.zego.advancedaudioprocessing.originalaudiodataacquisition.OriginalAudioDataAcquisitionActivity;
import im.zego.advancedaudioprocessing.rangeaudio.ui.RangeAudioActivity;
import im.zego.advancedaudioprocessing.soundlevelandspectrum.ui.SoundLevelAndSpectrumMainActivity;
import im.zego.advancedaudioprocessing.voicechange.VoiceChangeActivity;
import im.zego.encodinganddecoding.EncodingAndDecoding;
import im.zego.advancedstreaming.h265.H265LoginActivity;
import im.zego.advancedstreaming.lowlatencylive.LowLatencyLive;
import im.zego.quickstart.commonusage.CommonUsage;
import im.zego.quickstart.playing.Playing;
import im.zego.quickstart.publishing.Publishing;
import im.zego.quickstart.videochat.VideoChat;
import im.zego.quickstart.videochat.VideoChatLogin;
import im.zego.commonfeatures.roommessage.RoomMessageActivity;
import im.zego.advancedstreaming.streamByCdn.StreamByCdn;
import im.zego.advancedstreaming.streammonitoring.StreamMonitoring;
import im.zego.commonfeatures.commonvideoconfig.CommonVideoConfigActivity;
import im.zego.advancedstreaming.publishingmultiplestreams.ui.PublishingMultipleStreams;

import im.zego.customrender.ui.ZGVideoRenderTypeUI;
import im.zego.expresssample.R;
import im.zego.expresssample.adapter.MainAdapter;
import im.zego.expresssample.entity.ModuleInfo;
import im.zego.commonfeatures.videorotation.VideoRotationSelectionActivity;
import im.zego.others.videoobjectsegmentation.VideoObjectSegmentationLoginActivity;
import com.tencent.bugly.crashreport.CrashReport;


public class MainActivity extends AppCompatActivity {


    private MainAdapter mainAdapter = new MainAdapter();
    private static final int REQUEST_PERMISSION_CODE = 101;

    private RecyclerView moduleList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        CrashReport.initCrashReport(getApplicationContext(), "13a8646a49", false);

        if (!isTaskRoot()) {
            /* If this is not the root activity */
            Intent intent = getIntent();
            String action = intent.getAction();
            if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) {
                finish();
                return;
            }
        }
        moduleList = findViewById(R.id.module_list);
        mainAdapter.setOnItemClickListener((view, position) -> {
            boolean orRequestPermission = this.checkOrRequestPermission(REQUEST_PERMISSION_CODE);
            ModuleInfo moduleInfo = (ModuleInfo) view.getTag();
            if (orRequestPermission) {
                String module = moduleInfo.getModule();
                if (module.equals(getString(R.string.custom_video_rendering))){
                    ZGVideoRenderTypeUI.actionStart(MainActivity.this);
                }else if(module.equals(getString(R.string.common_video_config))){
                    CommonVideoConfigActivity.actionStart(MainActivity.this);
                }else if(module.equals(getString(R.string.video_for_multiple_users))){
                    VideoForMultipleUsersLogin.actionStart(MainActivity.this);
                }else if(module.equals(getString(R.string.video_rotation))){
                    VideoRotationSelectionActivity.actionStart(MainActivity.this);
                }else if(module.equals(getString(R.string.beautify_watermark_snapshot))){
                    BeautyWatermarkSnapshotActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.stream_monitoring))){
                    StreamMonitoring.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.publishing_multiple_streams))){
                    PublishingMultipleStreams.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.stream_by_cdn))){
                    StreamByCdn.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.low_latency_live))){
                    LowLatencyLive.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.h265))){
                    H265LoginActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.common_usage))){
                    CommonUsage.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.video_chat))){
                    VideoChat.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.publishing))){
                    Publishing.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.playing))){
                    Playing.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.room_message))){
                    RoomMessageActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.encoding_decoding))){
                    EncodingAndDecoding.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.custom_video_capture))){
                    CustomerVideoCaptureActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.log_version_debug))){
                    SettingActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.stream_mixing))){
                    MixerMainActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.recording))){
                    RecordingActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.media_player))){
                    MediaPlayerSelectionActivity.actionStart(MainActivity.this);
                } else if (module.equals(getString(R.string.camera))) {
                    CameraActivity.actionStart(MainActivity.this);
                } else if (module.equals(getString(R.string.multiple_rooms))){
                    MultipleRoomsActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.flow_control))){
                    FlowControlActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.network_and_performance))){
                    NetworkAndPerformanceActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.security))) {
                    SecurityActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.screen_sharing))) {
                    ScreenSharingActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.sei))){
                    SEIActivity.actionStart(MainActivity.this);
                }else if (module.equals(getString(R.string.voice_change_reverb_stereo))){
                    VoiceChangeActivity.actionStart(MainActivity.this);
                }
            }
        });

        // UI Setting
        moduleList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        moduleList.setAdapter(mainAdapter);
        moduleList.setItemAnimator(new DefaultItemAnimator());

        // Add Module
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.common_usage)).titleName(getString(R.string.quick_start)));
        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.video_chat)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.publishing)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.playing)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.video_for_multiple_users)).titleName(getString(R.string.scenes)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.common_video_config)).titleName(getString(R.string.common_features)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.video_rotation)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.room_message)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.stream_monitoring)).titleName(getString(R.string.advanced_streaming)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.publishing_multiple_streams)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.stream_by_cdn)));
        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.low_latency_live)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.h265)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.encoding_decoding)).titleName(getString(R.string.advanced_video_processing)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.custom_video_rendering)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.custom_video_capture)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.voice_change_reverb_stereo)).titleName(getString(R.string.advanced_audio_processing)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.ear_return_and_channel_settings)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.soundlevel_and_audioSpectrum)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.aec_ans_agc)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.audio_effect_player)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.original_audio_data_acquisition)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.custom_audio_capture_and_rendering)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.range_audio)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.subject_segmentation)).titleName(getString(R.string.others)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.super_resolution)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.beautify_watermark_snapshot)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.effects_beauty)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.stream_mixing)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.recording)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.media_player)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.camera)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.multiple_rooms)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.flow_control)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.network_and_performance)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.security)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.screen_sharing)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.sei)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.multi_video_source)));
//        mainAdapter.addModuleInfo(new ModuleInfo().moduleName(getString(R.string.log_version_debug)).titleName(getString(R.string.debug_config)));
    }

    // 需要申请 麦克风权限-读写sd卡权限-摄像头权限
    private static String[] PERMISSIONS_STORAGE = {
            "android.permission.CAMERA",
            "android.permission.RECORD_AUDIO",
        "android.permission.WRITE_EXTERNAL_STORAGE"};

    /**
     * 校验并请求权限
     */
    public boolean checkOrRequestPermission(int code) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(PERMISSIONS_STORAGE, code);
                return false;
            }
        }
        return true;
    }
}

VideoChat

//本页为打电话的视频显示与对话页面
package im.zego.quickstart.videochat;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import org.json.JSONObject;

import java.util.ArrayList;

import im.zego.commontools.logtools.AppLogger;
import im.zego.commontools.logtools.LogView;
import im.zego.commontools.logtools.logLinearLayout;
import im.zego.commontools.uitools.ZegoViewUtil;
import im.zego.keycenter.KeyCenter;
import im.zego.keycenter.UserIDHelper;
import im.zego.quickstart.R;
import im.zego.zegoexpress.ZegoExpressEngine;
import im.zego.zegoexpress.callback.IZegoApiCalledEventHandler;
import im.zego.zegoexpress.callback.IZegoEventHandler;
import im.zego.zegoexpress.constants.ZegoPlayerState;
import im.zego.zegoexpress.constants.ZegoPublisherState;
import im.zego.zegoexpress.constants.ZegoRoomState;
import im.zego.zegoexpress.constants.ZegoRoomStateChangedReason;
import im.zego.zegoexpress.constants.ZegoScenario;
import im.zego.zegoexpress.constants.ZegoUpdateType;
import im.zego.zegoexpress.entity.ZegoCanvas;
import im.zego.zegoexpress.entity.ZegoEngineProfile;
import im.zego.zegoexpress.entity.ZegoRoomConfig;
import im.zego.zegoexpress.entity.ZegoStream;
import im.zego.zegoexpress.entity.ZegoUser;


public class VideoChat extends AppCompatActivity {

    TextureView previewView;
    TextureView minplayView;

    TextView roomIDTextView;
    TextView userIDTextView;
    TextView publishStreamIDTextView;

    Button stopButton;

    String roomID;
    String userID;
    String publishStreamID;
    String playStreamID;

    ZegoExpressEngine engine;
    ZegoPublisherState publisherState;
    ZegoPlayerState playerState;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_chat);
        requestPermission();
        bindView();
        getVideoChatConfig();
        setupView();
        setLogComponent();
        createEngine();
        setEventHandler();
        loginRoom();
        setStopButtonEvent();
        setApiCalledResult();

    }

    public static void actionStart(Activity activity) {

        String userID = UserIDHelper.getInstance().getUserID();
        Intent intent = new Intent(activity, VideoChat.class);
        intent.putExtra("roomID", "001");
        intent.putExtra("userID", userID);
        intent.putExtra("publishStreamID", "s_" + userID);
        activity.startActivity(intent);
    }
    // Request for permission
    public void requestPermission() {
        String[] PERMISSIONS_STORAGE = {
                "android.permission.CAMERA",
                "android.permission.RECORD_AUDIO"};

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(PERMISSIONS_STORAGE, 101);
            }
        }
    }

    @Override
    protected void onDestroy() {
        // Destroy the engine
        ZegoExpressEngine.destroyEngine(null);
        super.onDestroy();
    }

    public void bindView() {
        previewView = findViewById(R.id.previewView);
        minplayView = findViewById(R.id.minplayView);

        roomIDTextView = findViewById(R.id.roomIDTextView);
        userIDTextView = findViewById(R.id.userIDTextView);
        publishStreamIDTextView = findViewById(R.id.publishStreamIDTextView);

        stopButton = findViewById(R.id.stopButton);
    }

    public void getVideoChatConfig() {
        roomID = getIntent().getStringExtra("roomID");
        userID = getIntent().getStringExtra("userID");
        publishStreamID = getIntent().getStringExtra("publishStreamID");
    }

    public void setupView() {
        setTitle("视频通话");

        roomIDTextView.setText(String.format("roomID:%s", roomID));
        userIDTextView.setText(String.format("userID:%s", userID));
        publishStreamIDTextView.setText(String.format("publishStreamID:%s", publishStreamID));

        minplayView.setVisibility(View.INVISIBLE);
    }

    // Set log component. It includes a pop-up dialog.
    public void setLogComponent() {
        logLinearLayout logHiddenView = findViewById(R.id.logView);
        logHiddenView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LogView logview = new LogView(getApplicationContext());
                logview.show(getSupportFragmentManager(),null);
            }
        });
    }

    public void createEngine() {
        // Initialize ZegoExpressEngine
        AppLogger.getInstance().callApi("Create ZegoExpressEngine");
        ZegoEngineProfile profile = new ZegoEngineProfile();
        profile.appID = KeyCenter.getInstance().getAppID();
        profile.appSign = KeyCenter.getInstance().getAppSign();

        // Here we use the high quality video call scenario as an example,
        // you should choose the appropriate scenario according to your actual situation,
        // for the differences between scenarios and how to choose a suitable scenario,
        // please refer to https://docs.zegocloud.com/article/14940
        profile.scenario = ZegoScenario.HIGH_QUALITY_VIDEO_CALL;

        profile.application = getApplication();
        engine = ZegoExpressEngine.createEngine(profile, null);
    }

    public void setEventHandler() {
        engine.setEventHandler(new IZegoEventHandler() {
            @Override
            public void onRoomStateChanged(String roomID, ZegoRoomStateChangedReason reason, int errorCode, JSONObject extendedData) {
                AppLogger.getInstance().receiveCallback("", roomID, reason.toString(), errorCode);
                if(reason == ZegoRoomStateChangedReason.LOGINED)
                {
                    startLive();
                }
            }

            @Override
            public void onRoomStreamUpdate(String roomID, ZegoUpdateType updateType, ArrayList<ZegoStream> streamList, JSONObject extendedData) {
                super.onRoomStreamUpdate(roomID, updateType, streamList, extendedData);
                if (updateType == ZegoUpdateType.ADD) {
                    // When the updateType is Add, stop playing current stream(if exist) and start playing new stream.
                    if (playerState != ZegoPlayerState.NO_PLAY) {
                        engine.stopPlayingStream(playStreamID);
                        playStreamID = null;
                    }

                    // No processing, just play the first stream
                    ZegoStream stream = streamList.get(0);
                    playStreamID = stream.streamID;
                    ZegoCanvas playCanvas = new ZegoCanvas(minplayView);
                    engine.startPlayingStream(playStreamID, playCanvas);
                } else {
                    // When the updateType is Delete, if the stream is being played, stop playing the stream.
                    if (playerState == ZegoPlayerState.NO_PLAY) {
                        return;
                    }
                    for (ZegoStream stream : streamList) {
                        if (playStreamID.equals(stream.streamID)) {
                            engine.stopPlayingStream(playStreamID);
                            playStreamID = null;
                        }
                    }
                }
            }

            @Override
            public void onPublisherStateUpdate(String streamID, ZegoPublisherState state, int errorCode, JSONObject extendedData) {
                super.onPublisherStateUpdate(streamID, state, errorCode, extendedData);
                AppLogger.getInstance().receiveCallback("", state.value());
                publisherState = state;
            }

            @Override
            public void onPlayerStateUpdate(String streamID, ZegoPlayerState state, int errorCode, JSONObject extendedData) {
                super.onPlayerStateUpdate(streamID, state, errorCode, extendedData);
                AppLogger.getInstance().receiveCallback("", state.value());
                playerState = state;
                if (playerState == ZegoPlayerState.PLAYING) {
                    minplayView.setVisibility(View.VISIBLE);
                } else {
                    minplayView.setVisibility(View.INVISIBLE);
                }
            }
        });
    }

    public void loginRoom() {
        // Login room
        AppLogger.getInstance().callApi("Login Room, roomID:%s", roomID);
        engine.loginRoom(roomID, new ZegoUser(userID));
    }

    public void startLive() {
        // Start preview
        AppLogger.getInstance().callApi("Start preview");
        ZegoCanvas previewCanvas = new ZegoCanvas(previewView);
        engine.startPreview(previewCanvas);

        // Start publish
        AppLogger.getInstance().callApi("Start publishing stream. streamID:%s", publishStreamID);
        engine.startPublishingStream(publishStreamID);
    }

    public void setStopButtonEvent() {
        stopButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Destroy Activity,
                finish();
            }
        });
    }

    public void setApiCalledResult(){
        // Update log with api called results
        ZegoExpressEngine.setApiCalledCallback(new IZegoApiCalledEventHandler() {
            @Override
            public void onApiCalledResult(int errorCode, String funcName, String info) {
                super.onApiCalledResult(errorCode, funcName, info);
                if (errorCode == 0){
                    AppLogger.getInstance().success("[%s]:%s", funcName, info);
                } else {
                    AppLogger.getInstance().fail("[%d]%s:%s", errorCode, funcName, info);
                }
            }
        });
    }
}

参考:https://doc-zh.zego.im/article/3125

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/562966.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何通过QQ进行手机号溯源

0x01 通过在线网址查询 Q绑在线查询&#xff1a;http://2k.24kz.cn/ 0x02 非数据库查询方法 如果上述的网址查询不到信息的号。会提示说没有找到 可能说明数据库中并无该qq号所绑定手机号的信息 开始正题&#xff1a; 第一步&#xff1a;点击添加账号&#xff0c;复制其QQ账…

Prompt Engineering | 文本转换prompt

LLM非常擅长将输入转换成不同的格式&#xff0c;例如多语种文本翻译、拼写及语法纠正、语气调整、格式转换等。 文章目录 1、文本翻译1.1、中文转西班牙语1.2、识别语种1.3、多语种翻译1.4、翻译正式语气1.4、通用翻译器 2、语气 / 风格调整3、格式转换4、拼写及语法纠正5、一个…

2021上半年

2021上半年 a 程序计数器pc d 更正一下&#xff1a;都是支持流水线技术的 DMA传送数据不需要CPU干预&#xff0c;和io设备并行工作&#xff08;存储周期&#xff09; c c c b c 关于TLS: B B D A D 保护的是&#xff1a;软件程序和文档 D B C B 前向传播&#xff1…

Containerd+Kubernetes搭建k8s集群

ContainerdKubernetes搭建k8s集群 文档说明安装软件的版本和下载地址环境说明服务器准备负载均衡IP地址准备 安装步骤环境设置关闭防火墙关闭SELinux关闭swap分区设置主机名称解析设置主机名称加载 br_netfilter 模块桥接的IPv4流量传递到iptables升级操作系统内核导入elrepo g…

Three.js--》实现3d汽车模型展览搭建

目录 项目搭建 初始化three.js基础代码 添加汽车模型展示 动态修改汽车模型 今天简单实现一个three.js的小Demo&#xff0c;加强自己对three知识的掌握与学习&#xff0c;只有在项目中才能灵活将所学知识运用起来&#xff0c;话不多说直接开始。 项目搭建 本案例还是借助…

makefile make 的隐式规则

文章目录 前言一、什么是隐式规则?二、典型隐式规则情况三、查看隐式规则四、隐式规则的禁用五、隐式规则的副作用总结 前言 一、什么是隐式规则? make 提供了一些常用的&#xff0c;例行的规则实现。 当相应的规则未提供时 &#xff0c; make 尝试使用隐式规则。 make 提供…

KDZK-F水轮发电机转子测试仪

一、产品概述 KDZK-F水轮发电机转子测试仪是判断发电机转子绕组有无匝间短路的专用仪器&#xff0c;可以自动、手动&#xff08;单向或双向&#xff09;测量转子绕组的电压、电流、阻抗、功率、相位角等参数。 二、功能与特点 旋转鼠标&#xff0c;操作更方便。 可选择快速的…

手写操作系统必掌握基础:函数调用约定

哈喽&#xff0c;我是子牙&#xff0c;一个很卷的硬核男人。深入研究Windows内核、Linux内核、Hotspot源码…聚焦做那些大家想学没地方学的课程&#xff1a;手写操作系统、手写虚拟机、手写模拟器、手写编程语言… 目前我已经做了两个成熟的课程&#xff1a;手写JVM、手写OS&a…

RTX4060 系 2399 元起,NVIDIA 又赢麻了

就在上周&#xff0c;NVIDIA 正式官宣了 RTX40 系显卡家族中更加主流的三款新品。 分别是 RTX 4060、RTX 4060 Ti 8G 以及 RTX 4060 Ti 16G。 其中 RTX 4060 Ti 8G 解禁时间为本月 23 日晚&#xff0c;24 日上架开售。 而 RTX 4060、RTX 4060 Ti 16G 要等到七月份。 价格部分…

2023年湖北建筑架子工报名流程?报名需要什么资料?考试一次过?

2023年湖北建筑架子工报名流程&#xff1f;报名需要什么资料&#xff1f;考试一次过&#xff1f; 建筑架子工证是建筑行业必备的证书之一&#xff0c;它是证明持有人可以在建筑工地上从事搭建脚手架、模板等施工工作的重要证明。启程别告诉你架子工的报名流程和资料。 百度搜一…

测试提效1-电商一键创单的实现

因电商项目不同场景下单特别多&#xff0c;而走前端流程特别慢。所以在某些测试场景需要特定配送方式 和 特定配送状态数据&#xff0c;本次实现快速创建。 1、前端页面 前端页面采用vue &#xff0c;页面需要的属性或字段&#xff0c;打算包括 环境env、店铺(准备了3种不同模…

一种新的爬虫网络解锁器

事出原由 遇到一个需要采集境外电商的需求&#xff0c;相比国内各种层出不穷的反爬手段&#xff0c;境外产品更注重于用户行为和指纹上。 所以笔者在想是否有类似于指纹浏览器的环境可以提供给爬虫采集器使用。 经过检索&#xff0c;找到了一种名为爬虫网络解锁器的新兴产品…

SAP: 建立HTTPS 连接时,报错 ICM_HTTP_SSL_PEER_CERT_UNTRUSTED

报错1&#xff1a; SSL handshake with tpm-uat.jlbry.cn:443 failed: SSSLERR_PEER_CERT_UNTRUSTED (-102)#The peers X.509 Certificate (chain) is untrusted##SapSSLSessionStartNB()SSSLERR_PEER_CERT_UNTRUSTED# SSL:SSL_read() failed (536872221/0x2000051d)# >…

【正点原子STM32连载】第十四章 蜂鸣器实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十四…

【无标题】ELISA-3(加装跟踪装置)—让群体协作更智能!

群体智能是近年来发展迅速的一个人工智能学科领域&#xff0c;通过对蚂蚁、蜜蜂等为代表的社会性昆虫群体行为的研究&#xff0c;实现分布式等智能行为。作为新一代人工智能的重要方向&#xff0c;群体智能通常用于无人机、机器人集群的协同作业。目前&#xff0c;群体智能在基…

零操作难度,轻松进行应用测试,App专项测试之Monkey测试完全指南!

目录 前言&#xff1a; 一、 Monkey测试的基础参数 1.1 事件类型参数&#xff1a; 1.2 覆盖包 1.3 事件数量 二、 Monkey测试的高级参数 2.1 稳定性级别 2.2 策略参数 2.3 包含选项参数 三、 附加代码 四、 总结 前言&#xff1a; 在移动应用的开发过程中&#xff0…

数据结构(C语言):有序顺序表的设计及相关操作函数

一、题目 有序顺序表的设计 实验要求&#xff1a; 有序顺序表的操作&#xff0c;包括初始化&#xff0c;求数据元素个数&#xff0c;插入&#xff0c;删除和取数据元素。放在头文件中&#xff08;建议尝试用动态数组实现有序顺序表&#xff09;&#xff1b;注意有序顺序表的…

【正点原子STM32连载】 第十七章 串口通信实验摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十七…

2023年25个Java8面试问题和答案

Java是一种非常流行的编程语言&#xff0c;从Android应用程序到物联网&#xff08;IoT&#xff09;无处不在。事实上&#xff0c;根据Codeplatoon的数据&#xff0c;Java在1年的招聘信息中排名#2022。考虑到它的普遍存在&#xff0c;对精通Java的专业人员的需求仍然很高也就不足…

【vlan高级特性——super vlan概述】

今天给大家分享Windows常用cmd网络命令&#xff0c;希望对大家能有所帮助&#xff01; 1、arp [option] [address] 显示/修改ARP缓存 执行命令&#xff1a;arp -a 参数说明&#xff1a; 显示和修改地址解析协议(ARP)使用的“IP 到物理”地址转换表。 ARP -s inet_addr eth…