raknet android,Android RakNet 系列之四 实现消息、语音、文件传输

简介

RakNet在Win平台上已经实现消息、语音、文件传输了,但在Android平台下尚未实现,笔者决定把源码移植到Android平台下测试。

详情

实现消息

项目自带Chat Example Client和Chat Example Server实现消息,源码简单易懂,此处就不介绍了,直接贴上图片。

1416622569_6379.jpg

测试通过,消息是以Toast方式显示的,图片未捕捉到显示。

实现语音

Win平台下实现语音是通过Portaudio进行的,Portaudio尚未支持Android,要实现语音怎么办?

Java层实现可以,但笔者觉得麻烦,决定移植Portaudio到Android。关于这方面的信息请查看博客:Android RakNet 系列之三 移植Portaudio。

实现原理:Raknet通过PortAudio进行语音采集以及播放,再通过RakVoice语音插件进行语音发送与接受,RakVoice中使用了speex编码传输。

Jni实现主要代码如下:

class Voice { //声音一个操作语音的类

public:

Voice();

virtual ~Voice();

void run(const char* ip); //关键执行

int portInAudioCallback(const void *inputBuffer);

int portOutAudioCallback(void *inputBuffer);

void waitForStop();

void stop();

public:

bool mute;

RakNet::RakPeerInterface *rakPeer;

RakNet::RakVoice rakVoice;

PaError err;

bool isStoped;

bool runState;

};void Voice::run(const char* ip) { //通过Ip连接对方机子,然后传输。

if (err != paNoError) {

LOGI("Pa_Initialize fail: %s",Pa_GetErrorText(err));

return;

}

mute = false;

PaStream *stream;

unsigned int maxConnectionsAllowed = 4;

unsigned int maxPlayersPerServer = 4;

unsigned short serverPort = 6000;

RakNet::SocketDescriptor socketDescriptor(serverPort, 0);

if (rakPeer->Startup(maxConnectionsAllowed, &socketDescriptor, 1) != RakNet::RAKNET_STARTED) {

LOGI("Startup fail:");

return;

}

rakPeer->SetMaximumIncomingConnections(maxPlayersPerServer);

rakPeer->AttachPlugin(&rakVoice);

rakVoice.Init(SAMPLE_RATE, FRAMES_PER_BUFFER * sizeof (short));

PaDeviceIndex numdev;

const PaDeviceInfo *info;

int i;

numdev = Pa_GetDeviceCount();

PaStreamParameters inparam, outparam;

memset(&inparam, 0, sizeof (PaStreamParameters));

inparam.device = Pa_GetDefaultInputDevice();

inparam.channelCount = 1;

inparam.sampleFormat = paInt16;

memset(&outparam, 0, sizeof (PaStreamParameters));

outparam.device = Pa_GetDefaultOutputDevice();

outparam.channelCount = 1;

outparam.sampleFormat = paInt16;

PaError err = Pa_OpenStream(&stream,

&inparam,

&outparam,

SAMPLE_RATE,

FRAMES_PER_BUFFER,

paClipOff,

PAInOutCallback,

this);

err = Pa_SetStreamFinishedCallback(stream, &StreamFinished );

if(err != paNoError){

LOGI("Cannot set stream finish callback");

return;

}

if (err != paNoError) {

LOGI("Pa_OpenStream fail: %s",Pa_GetErrorText(err));

return;

}

err = Pa_StartStream(stream);

if (err != paNoError) {

LOGI("Pa_StartStream fail: %s",Pa_GetErrorText(err));

return;

}

if (ip) {

LOGI("Connect: %s",ip);

rakPeer->Connect(ip, serverPort, 0, 0);

}

RakNet::Packet *p;

unsigned char typeId;

isStoped = false;

runState = true;

while (1) {

if(!runState)

{

Pa_AbortStream(stream);

Pa_CloseStream(stream);

isStoped = true;

return;

}

p=rakPeer->Receive();

while (p)

{

LOGI("Receive data from: %s guid",p->systemAddress.ToString(),p->guid.ToString());

if (p->data[0]==ID_CONNECTION_REQUEST_ACCEPTED)

{

LOGI("ID_CONNECTION_REQUEST_ACCEPTED from %s\n", p->systemAddress.ToString());

rakVoice.RequestVoiceChannel(p->guid);

}

else if (p->data[0]==ID_CONNECTION_ATTEMPT_FAILED)

{

LOGI("ID_CONNECTION_ATTEMPT_FAILED\n");

}

else if (p->data[0]==ID_RAKVOICE_OPEN_CHANNEL_REQUEST || p->data[0]==ID_RAKVOICE_OPEN_CHANNEL_REPLY)

{

LOGI("Got new channel from %s\n", p->systemAddress.ToString());

}

else if (p->data[0]==ID_NAT_TARGET_NOT_CONNECTED)

{

RakNet::RakNetGUID g;

RakNet::BitStream b(p->data, p->length, false);

b.IgnoreBits(8); // Ignore the ID_...

b.Read(g);

LOGI("ID_NAT_TARGET_NOT_CONNECTED for %s\n", g.ToString());

}

else if (p->data[0]==ID_NAT_TARGET_UNRESPONSIVE)

{

RakNet::RakNetGUID g;

RakNet::BitStream b(p->data, p->length, false);

b.IgnoreBits(8); // Ignore the ID_...

b.Read(g);

LOGI("ID_NAT_TARGET_UNRESPONSIVE for %s\n", g.ToString());

}

else if (p->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST)

{

RakNet::RakNetGUID g;

RakNet::BitStream b(p->data, p->length, false);

b.IgnoreBits(8); // Ignore the ID_...

b.Read(g);

LOGI("ID_NAT_CONNECTION_TO_TARGET_LOST for %s\n", g.ToString());

}

else if (p->data[0]==ID_NAT_ALREADY_IN_PROGRESS)

{

RakNet::RakNetGUID g;

RakNet::BitStream b(p->data, p->length, false);

b.IgnoreBits(8); // Ignore the ID_...

b.Read(g);

LOGI("ID_NAT_ALREADY_IN_PROGRESS for %s\n", g.ToString());

}

else if (p->data[0]==ID_NAT_PUNCHTHROUGH_FAILED)

{

LOGI("ID_NAT_PUNCHTHROUGH_FAILED for %s\n", p->guid.ToString());

}

else if (p->data[0]==ID_NAT_PUNCHTHROUGH_SUCCEEDED)

{

LOGI("ID_NAT_PUNCHTHROUGH_SUCCEEDED for %s. Connecting...\n", p->guid.ToString());

rakPeer->Connect(p->systemAddress.ToString(false),p->systemAddress.GetPort(),0,0);

}

else if (p->data[0]==ID_ALREADY_CONNECTED)

{

LOGI("ID_ALREADY_CONNECTED\n");

}

else if (p->data[0]==ID_RAKVOICE_CLOSE_CHANNEL)

{

LOGI("ID_RAKVOICE_CLOSE_CHANNEL\n");

}

else if (p->data[0]==ID_DISCONNECTION_NOTIFICATION)

{

LOGI("ID_DISCONNECTION_NOTIFICATION\n");

}

else if (p->data[0]==ID_NEW_INCOMING_CONNECTION)

{

LOGI("ID_NEW_INCOMING_CONNECTION\n");

}

else if(p->data[0]==ID_CONNECTION_LOST)

{

LOGI("ID_CONNECTION_LOST 可靠的数据包不能被传递到指定的分组系统");

}

else

{

LOGI("Unknown packet ID %i\n", p->data[0]);

}

rakPeer->DeallocatePacket(p);

p=rakPeer->Receive();

}

Pa_Sleep( 30 );

}

}

效果如图:

1416623290_6267.jpg

实现文件传输Win平台下的文件传输Demo直接移植到Android平台便可实现,代码如下:

class CBTransferInterface : public RakNet::FileListTransferCBInterface //传输文件接口

{

public:

bool OnFile(OnFileStruct *onFileStruct);

virtual void OnFileProgress(FileProgressStruct *fps);

virtual bool OnDownloadComplete(DownloadCompleteStruct *dcs);

};

// Sender progress notification

class TestFileListProgress : public RakNet::FileListProgress //进度通知

{

virtual void OnFilePush(const char *fileName, unsigned int fileLengthBytes, unsigned int offset, unsigned int bytesBeingSent, bool done, RakNet::SystemAddress targetSystem, unsigned short setID);

virtual void OnFilePushesComplete( RakNet::SystemAddress systemAddress, unsigned short setID );

virtual void OnSendAborted( RakNet::SystemAddress systemAddress );

};

class FileTransferClient //客户端

{

public:

int testTransfer(const char* ip,const char* filePath);

void stopTransfer();

void waitForStop();

public:

int transferStatus;

int isStoped;

};

效果如图:

1416623471_8674.jpg

结束      至此,在Android平台下已经实现了消息、语音、文件传输等功能,近期将实现视频。

原文:http://blog.csdn.net/banketree/article/details/41348543

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值