我正在开发Android 3.1平板电脑应用程序。
这个应用程序将运行一个线程。在服务上,我有以下代码:
public class UDPSocketBackgroundService extends Service
{
@Override
public void onCreate()
{
super.onCreate();
Log.v(TAG, "in onCreate()");
// xxxxxx
Looper.prepare();
mServiceHandler = new Handler() {
/**
*
*/
public void handleMessage(Message msg)
{
DatagramPacket packet = (DatagramPacket) msg.obj;
//String received = new String(packet.getData(), 0, packet.getLength());
Message backMsg = Message.obtain();
backMsg.arg1 = Activity.RESULT_OK;;
Bundle bundle = new Bundle();
bundle.putByteArray("CLIENT_DATA", packet.getData());
bundle.putString("CLIENT_HOST", packet.getAddress().getHostAddress());
bundle.putString("CLIENT_PORT", new Integer(packet.getPort()).toString());
backMsg.setData(bundle);
try
{
outMessenger.send(backMsg);
}
catch (android.os.RemoteException e1)
{
Log.w(getClass().getName(), "Exception sending message", e1);
}
}
};
Looper.loop();
}
但我不知道为什么(因为这是我第一次使用服务)我在这里得到一个例外:
Looper.prepare();
更新
服务的onBind活动:
public IBinder onBind(Intent intent)
{
Bundle extras = intent.getExtras();
// Get messager from the Activity
if (extras != null) {
outMessenger = (Messenger) extras.get("MESSENGER");
}
try
{
myThread = new UDPServerThread("X", 8888, mServiceHandler);
myThread.start();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return mMessenger.getBinder();
}
这是我如何从主活动启动服务:
protected void onResume()
{
super.onResume();
Intent intent = null;
intent = new Intent(this, UDPSocketBackgroundService.class);
// Create a new Messenger for the communication back
// From the Service to the Activity
Messenger messenger = new Messenger(handler);
intent.putExtra("MESSENGER", messenger);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
我做错了什么?
答案 0 :(得分:2)
1。服务不在后台线程上运行,而是在专用UI线程上运行。
2。在UI线程上使用UI工作是非常好的做法,非UI在非UI线程上工作,但是来自HoneyComb的成为规则
3. 因此,对于您的后台线程,请使用Thread will Handler或AsyncTask。
4。使用Handler在前台执行非UI工作,而后者需要UI线程调用Looper.loop()以获取服务的实际消息 ,所以无需显式调用 Looper.loop()或prepare()。
答案 1 :(得分:1)
服务在UI线程上运行,并且UI线程已经有一个looper,这就是你收到错误的原因。
如果您打算在后台线程中完成工作,那么您可能需要为要运行的代码创建一个新线程。
也许您可以查看HandlerThread。
答案 2 :(得分:1)
首先,Service
不会在后台线程上运行,因此您应该使用Thread
,AsyncTask
或IntentService
作为后台工作。其次,Service
已经初始化了一个Looper,您必须从代码中删除Looper.prepare()
和Looper.loop()
。