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

写在前面

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

技术探索

本来一开始是准备直接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;@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.module_list, parent, false);return new MyViewHolder(v);}@Overridepublic 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());}@Overridepublic 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;@Overrideprotected 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 SettingmoduleList.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;@Overrideprotected 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 permissionpublic 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);}}}@Overrideprotected void onDestroy() {// Destroy the engineZegoExpressEngine.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() {@Overridepublic void onClick(View v) {LogView logview = new LogView(getApplicationContext());logview.show(getSupportFragmentManager(),null);}});}public void createEngine() {// Initialize ZegoExpressEngineAppLogger.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/14940profile.scenario = ZegoScenario.HIGH_QUALITY_VIDEO_CALL;profile.application = getApplication();engine = ZegoExpressEngine.createEngine(profile, null);}public void setEventHandler() {engine.setEventHandler(new IZegoEventHandler() {@Overridepublic void onRoomStateChanged(String roomID, ZegoRoomStateChangedReason reason, int errorCode, JSONObject extendedData) {AppLogger.getInstance().receiveCallback("", roomID, reason.toString(), errorCode);if(reason == ZegoRoomStateChangedReason.LOGINED){startLive();}}@Overridepublic 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 streamZegoStream 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;}}}}@Overridepublic void onPublisherStateUpdate(String streamID, ZegoPublisherState state, int errorCode, JSONObject extendedData) {super.onPublisherStateUpdate(streamID, state, errorCode, extendedData);AppLogger.getInstance().receiveCallback("", state.value());publisherState = state;}@Overridepublic 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 roomAppLogger.getInstance().callApi("Login Room, roomID:%s", roomID);engine.loginRoom(roomID, new ZegoUser(userID));}public void startLive() {// Start previewAppLogger.getInstance().callApi("Start preview");ZegoCanvas previewCanvas = new ZegoCanvas(previewView);engine.startPreview(previewCanvas);// Start publishAppLogger.getInstance().callApi("Start publishing stream. streamID:%s", publishStreamID);engine.startPublishingStream(publishStreamID);}public void setStopButtonEvent() {stopButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {// Destroy Activity,finish();}});}public void setApiCalledResult(){// Update log with api called resultsZegoExpressEngine.setApiCalledCallback(new IZegoApiCalledEventHandler() {@Overridepublic 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.rhkb.cn/news/65635.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

情感脑机接口与跨被试情感模型问题研究

情感脑机接口与跨被试情感模型问题研究 基于最大分类器差异域对抗方法的跨被试脑电情绪识别研究引言部分关键要点提取MCD_DA 模型解读数据集创建以及处理模型训练步骤实验结果 Multisource Transfer Learning for Cross-Subject EEG Emotion RecognitionRELATED WORKMETHODSSou…

妈妈的情绪,决定孩儿子的未来

ISBN&#xff1a;978-7-5472-5951-1 页数&#xff1a;247页 作者&#xff1a;融智 阅读时间&#xff1a;2021-08-08 推荐指数&#xff1a;★★★★☆ 妈妈可能不是天才&#xff0c;但是可以成为天才的母亲。 过度慈爱会败子&#xff0c;过度严厉也会毁子。 父母真正的爱就是越…

2步就能完成的情感分析模型

ABSA&#xff08;Aspect Based Sentiment Analysis&#xff09;是一种在给定的语料库中同时提取&#xff08;co-extracting &#xff09;表达意见和&#xff08;事物&#xff09;属性/方面术语&#xff08;意见目标&#xff09;以及它们之间的关系的任务。 方面级情感分类是情…

家庭教育中有近一半是由母亲负责孩子学习,占49%,父亲负责仅占10%

近年来&#xff0c;随着国家经济的高速发展&#xff0c;国民对教育的需求越来越大&#xff0c;特别是对家庭教育的重视程度越来越高。家庭是人生的第一所学校&#xff0c;家长是孩子的第一任老师&#xff0c;要给孩子讲好“人生第一课”&#xff0c;帮助扣好人生第一粒扣子。 …

案例研究 | 运用设计冲刺,解决俄罗斯家庭暴力问题

问题 家庭暴力是一个困扰全球的问题&#xff0c;运用设计冲刺能帮我们解决它吗&#xff1f; 在俄罗斯&#xff0c;每5名妇女就有1名遭受到丈夫或伴侣的虐待&#xff0c;而这种情况在2017年国家将家庭虐待定为非刑事罪后更是急剧恶化。 于是&#xff0c;俄罗斯的一个律师和新闻…

母亲节营销案例大盘点,真的有被狠狠共情住

⼀直以来&#xff0c;节⽇营销都是品牌借势和消费者建⽴情感链接的好时机。尤其是在母亲节这个温情的⽇⼦⾥&#xff0c;借助催泪、温情的⼴告歌颂母爱的无私与伟⼤来打动消费&#xff0c;也成为品牌母亲节营销的标配。 随之⽽来的&#xff0c;越来越多的品牌也⾯临困局&#x…

酒店评论情感分析,亲妈级教程

酒店评论情感分析&#xff0c;采集与分词篇 开篇吐槽一下下。 类似携程这种生活类网站&#xff0c;还有电商类网站&#xff0c;不是驻守被爬的城墙内就是在反爬的道路上行走。不断的更新加密&#xff0c;批量化的采集不断破解并升级程式&#xff0c;并在网络之上布施教程&…

用孕妇的思维和孕妇对话——《用孩子的思维和孩子对话》

看惯了某鱼上经典的卖货话术&#xff0c;“不懂事怀孕了&#xff0c;遂出”。没想到我居然也快要当爸爸了。这几个月准爸爸的生活让我切身的体会到了孕妇的不容易以及陪伴孕妇的辛苦。本文不打算歌颂母亲或者替准爸爸们倒苦水&#xff0c;单纯总结思考一下孕期夫妻如何沟通。加…

(含完整代码)简易Android计算器的实现

文章结构 1、项目要求2、实现思路3、代码实现主文件子文件 4、效果预览 1、项目要求 其实老师的要求就是做一个简易的计算器&#xff0c;有两个文本框&#xff0c;一个按钮&#xff0c;然后实现加法即可。 但是我还是想做一个比较好康的计算器&#xff08;如下&#xff09;&am…

Android——在线计算器完整代码

实现效果 一、xml布局文件 这里采用线性布局&#xff0c;关于计算器的布局&#xff0c;可以查看之前的文章。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"and…

Qt简易计算器的代码实现

大二用qt写的简易计算机&#xff0c;已经修改完bug,请放心食用 输入的时候一定用按钮&#xff0c;不要直接在文本框中输入 在qt中新建这几个文件&#xff0c;运行就OK了 main.cpp #include "calculator.h" #include <QApplication>int main(int argc, char *…

chatgpt赋能python:如何打开Python黑色界面

如何打开Python黑色界面 Python黑色界面是一个流行的Python环境编辑器。很多Python开发者首选Python黑色界面来编写和运行Python程序。但是&#xff0c;很多人还不知道如何打开Python黑色界面。在这篇文章中&#xff0c;我们将介绍如何打开Python黑色界面&#xff0c;以及一些…

【无标题】分享3款好用的简易视频剪辑软件

分享3款好用的小白视频剪辑软件 本人是个短视频爱好者&#xff0c;经常需要剪辑视频&#xff0c;在实际操作中发现&#xff0c;那些专业的视频剪辑软件操作非常复杂&#xff0c;不易操作&#xff0c;而且文件又大。那些简单的视频剪辑软件小而精巧&#xff0c;操作方便&#xf…

怎么剪切视频中的一部分?不如试试这个软件

怎么剪切视频中的一部分&#xff1f;我们在进行视频剪辑的时候&#xff0c;需要导入大量的素材&#xff0c;我们不可能完整的保留整段素材。通常情况下&#xff0c;我们需要对已有的素材进行编辑分割。这里小编就来给大家介绍在电脑上对视频进行分割的方法。 怎么剪切视频中的一…

小众但意外觉得蛮好用的剪辑软件!纯良心分享

爱剪辑 有开屏广告&#xff0c;一共3个界面&#xff1a;首页、剪同款、我的。 剪辑、配乐、字幕、滤镜、加速、贴纸、配音等主流功能都有。 特色功能有剪裁视频、倒放视频、视频旋转、视频转换GIF、转场、提取音频、画中画等。 还可以拼接视频&#xff0c;不过不支持FLV等小众文…

AI伪原创混剪软件脚本,短视频伪原创剪辑工具必备神器

AI伪原创混剪脚本&#xff0c;伪原创剪辑必备神器【永久脚本详细教程】 AI伪原创混剪软件脚本&#xff0c;短视频伪原创剪辑工具必备神器 设备需求&#xff1a;电脑 软件截图&#xff1a; -------------------------------- 文章分享者&#xff1a;Linxiaoyu2022 文章的来源…

剪映电脑版超简单使用教程Mac

相机 我主要用到的两个键 点击开始创作导入本地视频 导入本地视频 将素材拖拽到时间线上 时间线面板操作 撤销、恢复、分割 撤销上一次操作也可以用快捷键 command z 定格、倒放、镜像、裁剪 剃刀 点击菜单的分割可以出来一个剃刀&#xff0c;分割更方便 选择模式 …

创业创业,有点风险,读取数据做个商务分析

1、起因 过完年了,作为程序也很老了,所以想搞个副业看看,但是盲目的创业是不行的,鲁迅先生说过:方向大于努力,所以选对方向很重要,数据调研第一步,不能盲目出招,浪费时间,浪费精力,最主要浪费我的血汗钱。 上班的时间基本都在点外卖,所以想做做外卖,因为自己是小…

精选个人创业计划

精选个人创业计划精选篇1 一、企业概况 以突出“新鲜”“精致”为主要特色。坐落于河北区昆纬路的一个小店&#xff0c;主营鲜花与礼品的零售。它没有亮丽的装潢设计&#xff0c;而是着重朴实的风格&#xff0c;突出了产品的“精”与“美”&#xff0c;成为人们五彩斑斓生活中不…

创业合伙人十个核心问题

导读&#xff1a; 我们见到&#xff0c;很多创业企业的股权分配&#xff0c;都是“时间的错位”&#xff1a;根据创业团队当下的贡献&#xff0c;去分配公司未来的利益。创业初期&#xff0c;不好评估各自贡献&#xff0c;创业团队的早期出资就成了评估团队贡献的核心指标。这导…