編輯:關於Android編程
RakNet在Win平台上已經實現消息、語音、文件傳輸了,但在Android平台下尚未實現,筆者決定把源碼移植到Android平台下測試。
項目自帶Chat Example Client和Chat Example Server實現消息,源碼簡單易懂,此處就不介紹了,直接貼上圖片。
vcq9z9TKvrXEo6zNvMaszrSytte9tb3P1Mq+oaM8L3A+PGg1Psq1z9bT79L0PC9oNT48cD5XaW7Gvcyoz8LKtc/W0+/S9MrHzai5/VBvcnRhdWRpb7340NC1xKOsUG9ydGF1ZGlvydDOtNans9ZBbmRyb2lko6zSqsq1z9bT79L01PXDtLDso788L3A+PHA+SmF2YbLjyrXP1r/J0tSjrLWrscrV3771tcPC6bezo6y+9rao0sbWslBvcnRhdWRpb7W9QW5kcm9pZKGjudjT2tXit73D5rXE0MXPosfrsum/tLKpv82jukFuZHJvaWQgUmFrTmV0IM+1wdDWrsj9INLG1rJQb3J0YXVkaW+hozwvcD48cD7Ktc/W1K3A7aO6UmFrbmV0zai5/VBvcnRBdWRpb7340NDT79L0ssm8r9LUvLCypbfFo6zU2c2ouf1SYWtWb2ljZdPv0vSy5bz+vfjQ0NPv0vS3osvN0+u908rco6xSYWtWb2ljZdbQyrnTw8HLc3BlZXix4MLrtKvK5KGjPC9wPjxwPkpuacq1z9bW99KqtPrC68jnz8KjujwvcD48cD48L3A+PHByZSBjbGFzcz0="brush:java;">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 );
}
}效果如圖:

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;
};
Android響應式編程(一)RxJava前篇[入門基礎]
1.RxJava概述ReactiveX與RxJava在講到RxJava之前我們首先要了解什麼是ReactiveX,因為RxJava是ReactiveX的一種java實現。
Android編程四大組件分別是什麼
Android開發四大組件分別是:活動(Activity):用於表現功能。服務(Service):後台運行服務,不提供界面呈現。廣播接收器(BroadcastReceiv
Android 屬性動畫進階總結篇(篇3)
1.總結之前學習的關於屬性動畫的筆記 和 學習了郭霖大神的 屬性動畫高級用法相關的博客之後的記錄2.學習loading… 2.1補間動畫 PK 屬性動畫在篇
Android雜談(22):AndroidStudio快捷鍵
本菜開源的一個自己寫的Demo,希望能給Androider們有所幫助,水平有限,見諒見諒.. https://github.com/zhiaixinyang/MyFir