我正在为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()运行时调用send,因为它监视传入流量,而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 +中)了吗?
答案 0 :(得分:1)
不是100%肯定,因为我没有堆栈跟踪,但是:
ComService
的构造函数在主线程(new ComService()
)上执行并且已经联网,因为AFAIK大多数InetAddress
方法尝试解析名称并且可以执行已经符合条件的dns查找“联网”。您必须捕获的IOException
也是一个强有力的指标。
尝试将代码从构造函数移动到run()
方法,它可能已经有效了。
答案 1 :(得分:-1)
我已经回答了类似问题here但是无论如何,将以下代码添加到你的oncreate()中你会没事的
if (android.os.Build.VERSION.SDK_INT > 9)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}