0

UDP チャット アプリを開発しています。すべてのネットワーク処理は、サービス内のスレッド内にあります。3.1 および 4.0 オペレーティング システムでこのエラー メッセージが表示されます。バージョン 2.3 以下では正常に動作しています。質問: バージョン 2.3 以下用とバージョン 3.0 以降用の 2 つのアプリを作成する必要がありますか? エラーは、LogCat に従ってwrite(byte[] out)メソッドが呼び出されたときに発生します。

ICS の StrictMode を無効にすると、アプリは正常に動作します。

public class ChatService extends Service { 
    private Binder binder;
    private ComThread comThread;

    public IBinder onBind(Intent intent) {
        return binder;
    }

    public void onCreate() {
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        binder = new ChatServiceBinder();
        start();
        return super.onStartCommand(intent, flags, startId);
    }

    public synchronized void start() {
        comThread = new ComThread();
        comThread.start();
    }

    public void onDestroy() {
        stop();
    }

    public void write(byte[] out) {
        comThread.write(out);
    }

    public synchronized void stop() {
        if (comThread != null) {
            comThread.cancel();
            comThread = null;
        }
    }

    private class ComThread extends Thread {
        private static final int BCAST_PORT = 2562;
    DatagramSocket mSocket;
    InetAddress myBcastIP, myLocalIP;

    public ComThread() {

        try {
            myBcastIP = getBroadcastAddress();
            if (D)
                Log.d(TAG, "my bcast ip : " + myBcastIP);

            myLocalIP = getLocalAddress();
            if (D)
                Log.d(TAG, "my local ip : " + myLocalIP);

            mSocket = new DatagramSocket(BCAST_PORT);
            mSocket.setBroadcast(true);

        } catch (IOException e) {
            Log.e(TAG, "Could not make socket", e);
        }
    }

    public void run() {

        try {

            byte[] buf = new byte[1024];
            if (D)
                Log.d(TAG, "run(), com thread startet");
            // Listen on socket to receive messages
            while (true) {
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                mSocket.receive(packet);

                InetAddress remoteIP = packet.getAddress();
                if (remoteIP.equals(myLocalIP))
                    continue;

                String s = new String(packet.getData(), 0,
                        packet.getLength());
                if (D)
                    Log.d(TAG, "run(), " + s);

                Message msg = new Message();
                msg.obj = s;
                msg.arg1 = MessageHandler.MSG_IN;
                state.getHandler().sendMessage(msg);

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Write broadcast packet.
     */
    public void write(byte[] buffer) {
        try {
            String data = new String(buffer);
            DatagramPacket packet = new DatagramPacket(data.getBytes(),
                    data.length(), myBcastIP, BCAST_PORT);
            mSocket.send(packet);
        } catch (Exception e) {
            Log.e(TAG, "write(), Exception during write", e);
        }
    }

    /**
     * Calculate the broadcast IP we need to send the packet along.
     */
    private InetAddress getBroadcastAddress() throws IOException {
        WifiManager mWifi = (WifiManager) state
                .getSystemService(Context.WIFI_SERVICE);

        WifiInfo info = mWifi.getConnectionInfo();
        if (D)
            Log.d(TAG, "\nWiFi Status: " + info.toString());

        // DhcpInfo is a simple object for retrieving the results of a DHCP
        // request
        DhcpInfo dhcp = mWifi.getDhcpInfo();
        if (dhcp == null) {
            Log.d(TAG, "Could not get dhcp info");
            return null;
        }

        int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
        byte[] quads = new byte[4];
        for (int k = 0; k < 4; k++)
            quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);

        // Returns the InetAddress corresponding to the array of bytes.
        return InetAddress.getByAddress(quads); // The high order byte is
                                                // quads[0].
    }

    private InetAddress getLocalAddress() throws IOException {

        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface
                    .getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf
                        .getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        return inetAddress;
                    }
                }
            }
        } catch (SocketException ex) {
            Log.e(TAG, ex.toString());
        }
        return null;
    }

    public void cancel() {
        try {
            mSocket.close();
        } catch (Exception e) {
            Log.e(TAG, "close() of connect socket failed", e);
        }
    }
}

public class ChatServiceBinder extends Binder {
    private ChatService service = ChatService.this;

    public ChatService getService() {
        return service;
    }
}        

}

}

ありがとう。

4

1 に答える 1

0

少し遅れており、非常に優れた答えではありませんが、Android 3 以降では、Runnable はサービス内にない限り許可されていると解釈されません (サブクラスではありません)。好きなようにほとんど何でも作成できる自由を考えると、これが制限的なチェックであることは知っていますが、UDP マルチキャストは、すべての Android 開発者が混乱させるものではありません。お役に立てれば。

于 2013-07-05T23:01:29.170 に答える