‘壹’ android能与电脑局域网吗
可以通过一款叫做‘ES文件管理器’的app实现
1、打开es文件浏览器,点击上面的三条横线(菜单)
‘贰’ 开发一个基于android的即时通讯软件,怎么通过局域网来让电脑上的虚拟机和手机上的软件都能运用服务器
做一个路由跳转。实现网络通信
‘叁’ android 局域网实时语音聊天音频流用什么编
一般如果应用需要进行大量数学运算时,推荐使用JNI在Java中调用C/C++编写的动态库,Java只负责逻辑和界面用户操作的相应,
你这个APP很简单分为以下几个模块
界面,与用户进行交互,需要具备Android界面的编程;
网络传输,需要掌握Java网络socket编程的知识,使用TCP传输编码后的音频帧;
语音编解码模块,由两部分构成。一是c/c++编写的动态库,二是Java声明本地native函数,并将c/c++实现的native函数进行封装,方便Java调用。这部分需要掌握Java中JNI使用的知识,c/c++编程,语音处理的方面的知识,例如数字信号处理。
而c/c++写的库一般不是我们自己实现的,而是引入第三方开源代码,这里的选择有很多,我了解到的有
ffmeg,很常用,就连暴风影音和QQ音乐据说用了他们的开源库,而没有遵守开源协议而进入了他们的黑名单。
speex,是国外的开源库,现已被Opus取代,但是speex多了一个预处理功能,例如降噪、自动增益、回音消除等等。
Superpowered,跨平台的,低延迟,功能多。
补充一点,Android现已支持纯C++的开发了,这个就需要NDK的配合,写出NativeActivity,然后就可以直接在C++中调用第三方的库了,而不用JNI这样繁琐,但是由于刚出来,教程不多,需要具备很多嵌入式、音视频采集处理的开发经验。
‘肆’ (三)Android局域网内语音对讲 基于UDP语音传输
之前研究了基于UDP的文字传输 点击打开链接 ,以及Android端的语音录制 点击打开链接 ,这篇文章就记录一下Android端局域网内的语音传输,简单的实现语音对讲,当然里面还存在着很多问题,包括语音不清晰啊、杂音多啊,不管了,先听见声音就行了。测试的时候两部手机,上图:
程序写了两个线程,一个用于录制AudioRecordThread,一个用于播放AudioTrackThread.
(一)录制与发送
@Override
public void run() {
if (mSocket == null)
return;
try {
mStartTime = System.currentTimeMillis();
audioRec.startRecording();
while (flag) {
try {
byte[] bytes_pkg = buffer.clone();
if (mRecordQueue.size() >= 2) {
int length = audioRec.read(buffer, 0, minBufferSize);
//获取音量大小
mVolume = getAudioColum(buffer);
System.out.println(TAG + "= " + mVolume);
Message message = mHandler.obtainMessage();
message.arg1 = (int) mVolume;
mHandler.sendMessage(message);
DatagramPacket writePacket;
InetAddress inet = InetAddress.getByName(inetAddressName);
writePacket = new DatagramPacket(buffer, length, inet, PORT);
writePacket.setLength(length);
System.out.println("AudioRTwritePacket = " + writePacket.getData().toString());
mSocket.send(writePacket);
}
mRecordQueue.add(bytes_pkg);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
audioRec.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
里面包含了获取音量大小,便于在页面上面展示,方法参考了 点击打开链接
private double getAudioColum(byte[] buffer) {
double sumVolume = 0.0;
double avgVolume = 0.0;
double volume = 0.0;
for (int i = 0; i < buffer.length; i += 2) {
int v1 = buffer[i] & 0xFF;
int v2 = buffer[i + 1] & 0xFF;
int temp = v1 + (v2 << 8);// 小端
if (temp >= 0x8000) {
temp = 0xffff - temp;
}
sumVolume += Math.abs(temp);
}
avgVolume = sumVolume / buffer.length / 2;
volume = Math.log10(1 + avgVolume) * 10;
return volume;
}
(二)接收与播放
@Override
public void run() {
if (mSocket == null)
return;
//从文件流读数据
audioTrk.play();
while (flag) {
DatagramPacket recevPacket;
try {
recevPacket = new DatagramPacket(buffer, 0, buffer.length);
mSocket.receive(recevPacket);
audioTrk.write(recevPacket.getData(), 0, recevPacket.getLength());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
audioTrk.stop();
}
(三)主页面 接收按钮事件
@OnClick({R.id.btn_receive})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_receive:
if (btnReceive.getText().toString().equals("开始接收")) {
btnReceive.setText("停止接收");
try {
if (audioTrackThread == null) {
audioTrackThread = new AudioTrackThread();
}
new Thread(audioTrackThread).start();
} catch (SocketException e) {
e.printStackTrace();
}
} else {
btnReceive.setText("开始接收");
audioTrackThread.setFlag(false);
}
break;
}
}
(四)发送按钮事件
ivSpeak.setOnTouchListener(new View.OnTouchListener() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//按下按钮开始录制
ivSpeak.setText("正在说话");
//显示录音提示
relativeLayout.setVisibility(View.VISIBLE);
try {
if (audioRecordThread == null) {
audioRecordThread = new AudioRecordThread(handler);
}
audioRecordThread.setInetAddressName(tvReceiveIp.getText().toString());
audioRecordThread.setFlag(true);
new Thread(audioRecordThread).start();
} catch (SocketException e) {
e.printStackTrace();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//松开按钮结束录制
ivSpeak.setText("按住说话");
relativeLayout.setVisibility(View.GONE);
audioRecordThread.setFlag(false);
mStopTime = audioRecordThread.getmStopTime();
mStartTime = audioRecordThread.getmStartTime();
creatMessageBean((mStopTime - mStartTime) / 1000, true);
break;
}
return true;
}
});
‘伍’ android多台设备局域网和非局域网socket通信问题
技术上是不需要外部的web服务器做中转的,你可以路由进来的。
在路由器上做地址映射就可以了,普通家用型的路由器也是支持的。
需要考虑的是路由的外部地址的问题,可以通过动态域名来解决