私の以前の質問を読んだ人は、すでにこれを知っているかもしれません: 私は現在、WiFi Direct の全体を把握しようとしています。私がこれまで行ってきたことは、接続を作成することです。私がやろうとしているのは、UDP 経由で groupOwner にパケットを送信することです (IP はもちろん知られています) - しかし、毎回途中で失われるようです..
これが私のコードの一部です。ファイルを受信するためのサービスと、バックグラウンドでファイルを送信するためのインテントサービスがあります。
FileReceiverService.java
@Override
public void run() {
Log.d(TAG, "Thread starting...");
try {
app.log("Opening UDP socket to receive files.");
DatagramSocket socket = new DatagramSocket(PORT);
app.log("Socket open!");
socket.setSoTimeout(5000);
app.log("Waiting for packet..");
while (isRunning && !isInterrupted()) {
DatagramPacket packet = new DatagramPacket(
new byte[WiFiPacket.PACKET_SIZE],
WiFiPacket.PACKET_SIZE);
try {
socket.receive(packet);
app.log("Received " + packet.getLength()
+ " bytes, trying to parse!");
parsePacket(packet);
} catch (SocketTimeoutException e) {
} catch (Exception e) {
app.log("Something went wrong: " + e.getMessage());
e.printStackTrace();
}
}
socket.close();
app.log("Closing UDP socket");
} catch (Exception e) {
e.printStackTrace();
}
}
定数 WiFiPacket.PACKET_SIZE が 1024*32 に設定されている場合 (「ERRBLABLA MSG too long」エラーをより高い値で受け取ったため、32 KBytes)。
FileTransferService.java
@Override
protected void onHandleIntent(Intent intent) {
App app = (App) getApplication();
Context context = getApplicationContext();
boolean rightIntent = false;
WiFiFile file = null;
if (intent.getAction().equals(ACTION_SEND_TEXT)) {
rightIntent = true;
file = WiFiFile.fromText(intent.getExtras().getString(EXTRAS_TEXT));
} else if (intent.getAction().equals(ACTION_SEND_FILE)) {
rightIntent = true;
file = WiFiFile.fromFile(intent.getExtras().getString(
EXTRAS_FILE_PATH));
}
if (rightIntent && file != null) {
app.getOnWiFiTransmissionChangedListener().onNewOutgoingTransfer(
file);
String text = intent.getExtras().getString(EXTRAS_TEXT);
String host = intent.getExtras().getString(
EXTRAS_GROUP_OWNER_ADDRESS);
DatagramSocket socket = null;
int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
Log.d(TAG, "Sending packets to " + host + ":" + port);
try {
socket = new DatagramSocket();
int bytesSent = 0;
for (WiFiPacket p : file) {
Log.d(TAG, "Preparing another packet..");
byte[] payload = p.getBytes();
DatagramPacket packet = new DatagramPacket(payload,
payload.length, InetAddress.getByName(host), port);
Log.d(TAG, "Sending packet..");
socket.send(packet);
bytesSent += payload.length;
Log.d(TAG, "Packet send! Contained " + payload.length
+ " bytes! All over we've sent about " + bytesSent
+ " bytes!");
List<WiFiFile> list = new ArrayList<WiFiFile>();
list.add(file);
app.getOnWiFiTransmissionChangedListener()
.onTransferProgressChanged(list);
}
app.getOnWiFiTransmissionChangedListener()
.onFileTransferSuccessful(file);
Log.d(TAG, "Client: Data written");
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
} finally {
if (socket != null) {
if (socket.isConnected()) {
socket.close();
}
}
}
}
}
コードは最善ではないかもしれませんが、今のところ私が気にかけているのは、いまいましいパケットを受信することだけです。:)
参考までに: クラス WiFiFile のインスタンスを PACKET_SIZE 制限を超えない WiFiPackets に分割しているため、ファイルのオフセット、全長、送信者 (ユーザー名/inetaddress) などに関する何らかの独自のヘッダー情報が含まれています。それ。私のロギングは、約 25KBytes が送信されたことを示しています。私の知る限り、UDP パケットは途中で簡単にドロップされますが、約 10 回試してみましたが、毎回 25KB のパケットが失われる可能性は非常に低いと思います。
私が見逃しているものはありますか?何時間も前から自分のコードをじっと見つめていて、それを理解しようとして、コードにデバッグ/ログ ステートメントをどんどん入れていますが、何の進展もありません。
ありがとう!
PS:
IP アドレスとポートが正しい。
PS2:
AndroidManifest.xml
<uses-feature
android:name="android.hardware.wifi.direct"
android:required="true" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />