【Android App】实战项目之仿微信的视频通话(附源码和演示 超详细必看)
需要源码请点赞关注收藏后评论区留言私信~~~
虽然手机出现许多年了,它具备的功能也越来越丰富,但是最基本的通话功能几乎没有变化。从前使用固定电话的时候,通话就是听声音;如今使用最新的智能手机,通话仍旧是听声音。 只闻其声不见其人的状况持续了好多年,既然手机自带的通话功能不支持视频画面,只好通过App自身实现了,比如微信就支持视频通话功能。通话双方一边对话,一边在手机屏幕上看着对方,感觉就像面对面交谈那般亲切。
一、需求描述
视频通话的请求方点击视频通话菜单项,接收方会自动打开等待通话界面。
接收方点击接听按钮,表示同意视频通话,之后双方的微信都切到接通了的视频通话界面。
任何一方点击挂断按钮,都将结束视频通话过程。
二、功能分析
视频童话不但要实时传输语音,还要实时传输画面,这对即时性要求很高,从用户界面到后台服务,视频通话主要集成了以下技术
(1)模糊位图:等待接听界面的背景可使用对方的模糊头像。
(2)音频管理器:按下音量加减键可以调节通话音量。
(3)Socket通信:与拨号事件有关的信令管理,需要采取Socket通信与后端服务器交互。
(4)移动数据格式JSON:客户端与服务器之间传输信令,需要把信令内容封装为JSON格式。 (5)实时音视频:开源库WebRTC适用于一对一的视频传输。
下面介绍代码模块之间的关系
(1)ContactListActivity.java:这是联系人的列表界面。
可以分解为下列三类操作
1:分别侦听好友上线和好友下线时间,在好友上线时将他加入联系人列表,在好友下线时将他从联系人列表移除
2:点击某位好友的头像,确认将要与其视频通话后打开视频通话等待界面3:未在视频通话时需要侦听好友通话事件 一旦收到某位好友的通话请求就立即跳到等待接听界面
(2)ContactVideoActivity.java:这是视频通话的预览界面,发起方与接收方通用。
(3)服务端HttpServer模块中的VideoChatServer.java:处理Socket通信后端的信令消息传输。
视频通话的发起方与接收方的通话处理有所不同 主要区别如下
1:发起方发起通话请求之后需要侦听对方的接听事件,只有对方接受请求同意接听才能调用createOffer方法为其创建音视频供应
2:接收方只要按下接听按钮就表示同意通话请求,那么在收到对方的媒体能力时就应该调用createAnswer方法为其创建音视频答复
三、效果分析
联系人列表如下
四、代码
部分代码如下 全部代码请点赞关注收藏后评论区留言私信~~~
package com.example.live;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.example.live.adapter.EntityListAdapter;
import com.example.live.bean.EntityInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.socket.client.Socket;
public class ContactListActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
private final static String TAG = "ContactListActivity";
private EntityListAdapter mAdapter; // 联系人的列表适配器
private Map<String, EntityInfo> mContactMap = new HashMap<>(); // 联系人的名称映射
private List<EntityInfo> mContactList = new ArrayList<>(); // 联系人列表
private Socket mSocket; // 声明一个套接字对象
private String mSelfName; // 我的昵称
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_list);
initView(); // 初始化视图
initSocket(); // 初始化套接字
}
// 初始化视图
private void initView() {
TextView tv_title = findViewById(R.id.tv_title);
tv_title.setText("联系人列表");
findViewById(R.id.iv_back).setOnClickListener(v -> finish());
ListView lv_contact = findViewById(R.id.lv_contact);
mAdapter = new EntityListAdapter(this, mContactList);
lv_contact.setAdapter(mAdapter);
lv_contact.setOnItemClickListener(this);
}
// 初始化套接字
private void initSocket() {
mSelfName = getIntent().getStringExtra("self_name");
Log.d(TAG , "initSocket "+mSelfName);
mSocket = MainApplication.getInstance().getSocket();
mSocket.connect(); // 建立Socket连接
// 开始监听好友上线事件
mSocket.on("friend_online", (args) -> {
String friend_name = (String) args[0];
if (friend_name != null) {
// 把刚上线的好友加入联系人列表
mContactMap.put(friend_name, new EntityInfo(friend_name, "好友"));
mContactList.clear();
mContactList.addAll(mContactMap.values());
runOnUiThread(() -> mAdapter.notifyDataSetChanged());
}
});
// 开始监听好友下线事件
mSocket.on("friend_offline", (args) -> {
String friend_name = (String) args[0];
if (friend_name != null) {
mContactMap.remove(friend_name); // 从联系人列表移除已下线的好友
mContactList.clear();
mContactList.addAll(mContactMap.values());
runOnUiThread(() -> mAdapter.notifyDataSetChanged());
}
});
// 开始监听好友通话事件
mSocket.on("friend_converse", (args) -> {
String friend_name = (String) args[0];
// 接收到好友的通话请求,于是跳到视频通话页面
Intent intent = new Intent(this, ContactVideoActivity.class);
intent.putExtra("self_name", mSelfName); // 我的昵称
intent.putExtra("friend_name", friend_name); // 好友昵称
intent.putExtra("is_offer", false); // 是否为发起方
startActivity(intent);
});
mSocket.emit("self_online", mSelfName); // 通知服务器“我已上线”
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSocket.connected()) { // 已经连上Socket服务器
mSocket.emit("self_offline", mSelfName); // 通知服务器“我已下线”
mSocket.off("friend_online"); // 取消监听好友上线事件
mSocket.off("friend_offline"); // 取消监听好友下线事件
mSocket.off("friend_converse"); // 取消监听好友通话事件
mSocket.disconnect(); // 断开Socket连接
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
EntityInfo friend = mContactList.get(position);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(String.format("你是否要跟%s视频通话?", friend.name));
builder.setPositiveButton("是", (dialog, which) -> {
// 想跟好友通话,就打开视频通话页面
Intent intent = new Intent(this, ContactVideoActivity.class);
intent.putExtra("self_name", mSelfName); // 我的昵称
intent.putExtra("friend_name", friend.name); // 好友昵称
intent.putExtra("is_offer", true); // 是否为发起方
startActivity(intent);
});
builder.setNegativeButton("否", null);
builder.create().show();
}
@Override
protected void onRestart() {
super.onRestart();
Toast.makeText(this, "视频通话已结束", Toast.LENGTH_SHORT).show();
}
}
创作不易 觉得有帮助请点赞关注收藏~~~
相关文章
- Flask中的请求上下文和应用上下文
- 腾讯入资东方金信数亿元,共建大数据生态体系
- 浅谈大数据开发工程师的两年工作经验总结
- 大数据应用案例:Dealer Tire通过大数据预测消费者何时需要轮胎
- 医疗大数据:如何实现商业化变现?
- 大数据分析建模及其应用建议
- 招聘行业大数据应用场景分析
- 大数据入门学习必读好书推荐,请收藏!
- 区块链与大数据的整合,未来必然趋势
- 如今的大数据究竟发展到了什么阶段
- InterSystems IRIS医疗版助力东华医为推动中国医疗行业数字化转型
- 大数据产业进入提质增效关键期
- 社交网络大数据的应用有多大的价值
- 大数据安全防护方法研究与建议
- InterSystems IRIS 数据平台通过AWS云应用商店认证
- 大数据在医疗行业中的5种应用
- 中国大地保险数据管理应用中心大数据应用平台案例分析
- 大数据在应急管理中的应用
- 大数据:产业链条将更为完备
- 2019年大数据发展将走向何方