0

我正在开发一个 UDP 聊天应用程序。所有网络处理都在服务的线程内。对于 3.1 和 4.0 操作系统,我仍然收到此错误消息。对于 2.3 及以下版本,它工作正常。问题:我是否应该创建两个应用程序,一个用于 2.3 及以下版本,另一个用于 3.0 及更高版本?根据 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 回答