我正在使用Wifi Direct检测并连接到后台服务中的设备。
当建立WifiDirect连接时,我分别为服务器(GO)和客户端启动serverThread和Client Thread。
我现在的问题是,我不知道如何使工作线程与UI线程通信。
我所做的是在ClientThread和Server线程中创建了一个looper和一个处理程序,并为它创建了一个处理程序来获取作业。 正确处理客户端/服务器之间的套接字连接。
但问题是我不知道如何将数据从UI线程发送到工作线程。
我该怎么办?
这是代码:
在建立连接时的服务中,我启动线程:
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
Log.d(MainActivity.TAG, "groupowneradress"+ info.groupOwnerAddress.getHostAddress());
if (info.groupFormed && info.isGroupOwner) {
if (WifiDirectStatus!=1){
isgroupowner=true;
ServerDataThread serverThread= new ServerDataThread(PORT);
serverThread.start();
WifiDirectStatus=1;
}
} else if (info.groupFormed) {
if (WifiDirectStatus!=2){
ClientDataThread clientThread= new ClientDataThread(info.groupOwnerAddress.getHostAddress(),PORT);
clientThread.start();
WifiDirectStatus=2;
}
}
}
客户端线程例如:
public class ClientDataThread extends Thread {
public Handler clientHandler;
private static Socket socket=null;
private static final int SOCKET_TIMEOUT = 5000;
private int port;
private String host;
private BufferedReader in=null;
public PrintWriter out=null;
static final int MSG_CLIENT = 2;
ClientDataThread(String host, int port){
this.port=port;
this.host=host;
}
@Override
public void run(){
try{
Log.d(MainActivity.TAG, "ask for connection to the server");
socket=new Socket();
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Log.d(MainActivity.TAG, "connection socket has been established");
try{
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
out= new PrintWriter(socket.getOutputStream());
Log.d(MainActivity.TAG, "The Printwriter is equal to"+out.toString());
Thread t1=new Thread(new Receive_Client(in));
t1.start();
}catch(IOException e){
Log.d(MainActivity.TAG, "the client disconnect");
}
}catch (UnknownHostException e) {
Log.d(MainActivity.TAG, "impossible to connect to the host"+socket.getLocalSocketAddress());
}catch (IOException e) {
Log.d(MainActivity.TAG, "No Server Listening the port"+socket.getLocalPort());
}
Looper.prepare();
clientHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_CLIENT:
Log.d(MainActivity.TAG,"CDS has received the following message to send to the server"+(String)msg.obj);
try{
out.println((String)msg.obj);
out.flush();
Log.d(MainActivity.TAG, "The message has been sent to the server");
}catch (Exception e){
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
};
final Messenger mMessenger = new Messenger(clientHandler);
Looper.loop();
}
}
在主要活动中,每当我有新的位置更新时,我都想向工作线程发送消息:
public void onLocationChanged(Location location) {
Log.d(MainActivity.TAG, "location changed"+Double.toString(location.getLatitude())+Double.toString(location.getLongitude()));
if (mBound){
Log.d(MainActivity.TAG,"Wifi direct Status"+mDeviceListService.getWifiDirectStatus());
if (mDeviceListService.getWifiDirectStatus()==1){
// This Device acts as a Server
}
if (mDeviceListService.getWifiDirectStatus()==2){
Message msg= Message.obtain(null, ClientDataThread.MSG_CLIENT);
msg.obj= "bonjour";
clientHandler.sendMessage(msg);
}
答案 0 :(得分:0)
声明BroadcastReveiver
的主要好处是,您可以随时发出操作,并随时声明接收器,因此它适用于复杂的工作流程。
您只需声明接收者要接收信息的位置:
class ActivityBroadcast extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(CustomActions.RECEIVEMYDATA)) {
final String mydata = intent.getStringExtra("mydata");
if ((mydata != null) && (!mydata.isEmpty())) {
// Do your staff
...
}
}
}
}
如您所见,您将使用Intent
,因此您要发送的数据必须是可序列化的或可分割的。
另一件事是你必须为某些actions
注册你的接收器,这意味着你的接收器只会听取这个动作,这样你知道你想要处理的数据。尽管Android已经有一些内置动作,但我强烈建议您定义自己的动作。您可以这样做,只是声明一个公共类具有公共自己的操作。在我的情况下,您会看到我使用CustomActions.RECEIVEMYDATA
,这只是一个个性化且独特的String
。
您现在只需申报服务,注册您的行动并注册。未注册的接收者不会听取任何事情。
final ActivityBroadcast broadcast_signal = new ActivityBroadcast();
final IntentFilter iFilter= new IntentFilter();
iFilter.addAction(CustomActions.RECEIVEMYDATA);
LocalBroadcastManager.getInstance(this).registerReceiver(broadcast_signal, iFilter);
您可能会看到这是注册为本地广播接收器。这意味着您将在应用程序中注册操作。还有另一种广播接收器,它可能用于在应用范围内进行通信,在这种情况下,您使用全球广播接收器。
还剩下两件事:
第一种是将信号发送到接收器,因此无论何时何地,都可以使用以下内容:
final Intent intentResult = new Intent(CustomActions.RECEIVEMYDATA);
intentResult.putExtra("mydata", "data to send");
LocalBroadcastManager.getInstance(this).sendBroadcast(intentResult);
如果不再需要广播接收器,请不要忘记取消注册。对于此和注册,您应该记住Activity
的生命周期,并在需要时注销/注册。
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcast_signal);