0

我正在为 android os 2.3 及更高版本编写一个聊天程序。我一直在关注一些示例,并让它与我在 OS 2.3.x 上的所有额外花里胡哨的东西完美配合。

我的问题来自 OS > 2.3.x 即蜂窝,特别是 ICS(我有一个用于测试的 ICS 设备)。

我无法发送(数据包)。它每次都会因错误而崩溃。这里指出的答案似乎是在服务中运行线程。

不幸的是,情况一直如此 - 我想打开额外的窗口并在将数据传递回主活动之前保持服务抓取数据,不管主窗口可能会打开另一个窗口 - 当您返回整个聊天历史记录时,包括你错过的一切。

任何人都可以指出我需要做什么才能在每次代码命中 OS 4.0(ICS)中的发送(数据包)时不释放错误?

提前致谢。服务的完整来源在这里。

package com.rpg.phg.themesh;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.DhcpInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

/**
 * This class does all the work for sending and receiving broadcast packets. 
 * It has a thread that listens for incoming packets.
 */
public class TheMesh_ChatService extends Service 
{
// Debugging
private static final String TAG = "TheMesh_ChatService";
private static final boolean D = true;
private static String myIP = null;

// Member fields
private final Handler mHandler;
private ComService mConnectedService;

Context mContext ;
/**
 * Constructor. Prepares a new Broadcast service.
 * @param context  The UI Activity Context
 * @param handler  A Handler to send messages back to the UI Activity
 */
public TheMesh_ChatService(Context context, Handler handler, String ourIP) {
    //mAdapter = BluetoothAdapter.getDefaultAdapter();
    mContext = context;
    mHandler = handler;
    myIP = ourIP;
}


/**
 * Start the chat service. Specifically start ComThread to begin 
 * listening incoming broadcast packets. 
 */
public synchronized void start() {
    if (D) Log.d(TAG, "Started Service");

    mConnectedService = new ComService();
    mConnectedService.start();
}


/**
 * Stop thread
 */
public synchronized void stop() {
    if (D) Log.d(TAG, "stop");
    if (mConnectedService != null) {mConnectedService.cancel(); mConnectedService = null;}
}


public void write(byte[] out, String IP) {
    mConnectedService.write(out, IP);
}


/**
 * This thread handles all incoming and outgoing transmissions.
 * 
 * This actually needs to be turned onto the TheMesh_ChatService
 */    
private class ComService extends Thread {
    // Should we create a Thread here? 
    // It *should* stay running until the service ends...
    private static final int BCAST_PORT = 2568;
    DatagramSocket mSocket ;

    InetAddress myBcastIP, myLocalIP, myRemoteIP = null ;

    public ComService() {

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

               //myLocalIP  = getLocalAddress();
               myLocalIP =  InetAddress.getByName(myIP);
               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]; 

            //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, "Received response " + s); 

                // Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(TheMesh_PAN.MESSAGE_READ,-1,-1, s)
                .sendToTarget();
            } 
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
      * Write broadcast packet.
      */
    public void write(byte[] buffer, String IP) {

        try {
            String data = new String (buffer);
            if (IP.equalsIgnoreCase("ALL"))
            {
                DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(), 
                    myBcastIP, BCAST_PORT);
                mSocket.send(packet); // logcat shows crash here!
            } else
            {
                myRemoteIP = InetAddress.getByName(IP); // Will this generate Exceptions if lookup fails?
                DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(), 
                        myRemoteIP, BCAST_PORT);
                mSocket.send(packet); // and logcat shows crash here.
            }
            // Share the sent message back to the UI Activity
            mHandler.obtainMessage(TheMesh_PAN.MESSAGE_WRITE, -1, -1, data)
                    .sendToTarget();
        } catch (Exception e) {
            Log.e(TAG, "Exception during write", e);
        }
    }


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

      WifiInfo info = mWifi.getConnectionInfo();
      if(D)Log.d(TAG,"\n\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);

      return InetAddress.getByAddress(quads); // The high order byte is quads[0].
    }  

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

@Override
public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
}
}

这一切都按原样工作。大部分程序都取自“broadcastchat4”(对不起,我忘记了我是从哪个网站获得的)。我已经添加到它,尤其是调用程序。

一旦从 write 函数内部调用 send (在 run() 运行时调用它,因为它监视传入流量,而 write 处理传出流量),我在 logcat 中得到以下信息:

09-22 19:32:24.959: E/TheMesh_ChatService(17320): Exception during write
09-22 19:32:24.959: E/TheMesh_ChatService(17320): android.os.NetworkOnMainThreadException
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:175)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at libcore.io.IoBridge.sendto(IoBridge.java:463)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:182)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at java.net.DatagramSocket.send(DatagramSocket.java:287)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.rpg.phg.themesh.TheMesh_ChatService$ComService.write(TheMesh_ChatService.java:146)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.rpg.phg.themesh.TheMesh_ChatService.write(TheMesh_ChatService.java:69)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.rpg.phg.themesh.TheMesh_PAN.sendMessage(TheMesh_PAN.java:513)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.rpg.phg.themesh.TheMesh_PAN.access$11(TheMesh_PAN.java:494)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.rpg.phg.themesh.TheMesh_PAN$3.onKey(TheMesh_PAN.java:264)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.View.dispatchKeyEvent(View.java:5495)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1246)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1246)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1246)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1246)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1246)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1246)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1879)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1361)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.app.Activity.dispatchKeyEvent(Activity.java:2324)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1806)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3327)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2597)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.os.Handler.dispatchMessage(Handler.java:99)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.os.Looper.loop(Looper.java:137)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at android.app.ActivityThread.main(ActivityThread.java:4424)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at java.lang.reflect.Method.invokeNative(Native Method)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at java.lang.reflect.Method.invoke(Method.java:511)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
09-22 19:32:24.959: E/TheMesh_ChatService(17320):   at dalvik.system.NativeStart.main(Native Method)

关于如何使这个 ICS 工作的任何想法(实际上我怀疑它不会在蜂窝或更高版本上工作,因为网络更改似乎已合并到 v3+ 中)工作?

4

2 回答 2

1

不是 100% 确定的,因为我没有堆栈跟踪,但是:

的构造函数在ComService主线程(你必须抓住的也是一个强有力的指标。new ComService()InetAddressIOException

尝试将代码从构造函数移动到run()方法,它可能已经工作了。

顺便说一句:您实际上不应该在构造函数中执行网络或长时间运行的任务。只是简单的任务。

于 2012-09-21T12:07:41.230 回答
-1

我已经在这里回答了类似的问题,但无论如何,将以下代码添加到您的 oncreate() 中,您会没事的

        if (android.os.Build.VERSION.SDK_INT > 9)
         {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
          }
于 2012-09-21T11:59:50.440 回答