我的Android应用程序使用线程从通过USB连接的PC侦听套接字连接。在PC打开连接之后的某个时刻(响应某些用户驱动的事件)我想通过它发送一些数据。
public void onCreate(Bundle savedInstanceState) {
// SNIP: stuff and nonsense
connection = new Thread(new ServerThread());
connection.start();
}
public boolean onTouchEvent(MotionEvent event) {
// SNIP: decide what to do; create string 'coordString'
Message coordMsg = coordHandler.obtainMessage();
Bundle coordMsgData = new Bundle();
coordMsgData.putString("coords", coordString);
coordMsg.setData(coordMsgData);
if(coordHandler!=null)
{
coordHandler.sendMessage(coordMsg);
}
return false;
}
public class ServerThread extends Thread
{
public void run() {
this.setName("serverThread");
Looper.prepare();
coordHandler = new Handler()
{
@Override
public void handleMessage(Message msg) {
Log.v(INNER_TAG,"here");
}
};
// SNIP: Connection logic here
Looper.loop();
}
}.
多年来,我一直在摸不着头脑,想知道为什么我从未在触摸事件后看到INNER_TAG
的值出现在我的日志中。我可以使用日志调试来跟踪执行到coordHandler!=null
块,但处理程序似乎永远不会触发。
然后它让我感到震惊:线程可能在完成连接后退出。 D'呃!不太确定我以前发生过什么事情,但我会因为Loop
正在做一些神奇的事情而将其归咎于此。
所以我的问题是:如何保持我的线程运行?官方Android dev reference on threads简要提及
线程也可以成为守护进程,使其在后台运行。
这自然使我的* nix感觉刺痛。 (顺便说一下,你看过新的蜘蛛侠电影了吗?它还不错。)守护进程是答案吗?或者我完全失去了情节?
答案 0 :(得分:2)
在Android中使用服务。
您可以使用服务在后台运行..
请看这个链接:
http://developer.android.com/reference/android/app/Service.html
请参阅此链接以获取示例:
Example: Communication between Activity and Service using Messaging
答案 1 :(得分:0)
将connection = new Thread(new ServerThread());
更改为:connection = new ServerThread();
设置/获取处理程序实例时可能会添加synchronized块(毕竟它位于不同的线程中))
循环实际上是神奇的;)
在onDestroy中退出Looper for serverThread
最后但并非最不重要(虽然它与Handler / Looper主题无关,可能是你从未在日志中看到你期望的原因):而不是boolean onTouchEvent(MotionEvent event)
使用boolean dispatchTouchEvent(MotionEvent ev)
作为因文档而导致的onTouchEvent为Called when a touch screen event was not handled by any of the views under it.
,因此可能永远不会调用此处理程序方法
编辑:
你确定它执行sendMessage吗?那么为什么你要使用Log.v
?它假定您将日志记录级别设置为详细,否则将放弃日志。我建议使用Log.i
。
也许试试这段代码:
ServerThread connection;
Handler coordHandler;
public void onCreate(Bundle savedInstanceState) {
connection = new ServerThread();
connection.start();
}
@Override
protected void onDestroy() {
synchronized (this) {
if(coordHandler != null) {
coordHandler.getLooper().quit();
}
}
super.onDestroy();
}
public boolean dispatchTouchEvent(MotionEvent event) {
synchronized (this) {
if(coordHandler == null) {
Log.i(INNER_TAG, "Handler is null");
}
else {
Log.i(INNER_TAG, "Handler exists");
coordHandler.sendMessage(
coordHandler.obtainMessage(
0, event.toString()));
}
}
return false;
}
synchronized void setCoordHandler(Handler handler) {
coordHandler = handler;
}
public class ServerThread extends Thread {
public void run() {
this.setName("serverThread");
Looper.prepare();
setCoordHandler(new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i(INNER_TAG, "Inside handler");
}
});
Looper.loop();
}
}