我正在构建一个运行服务的Android应用程序,它有一个侦听tcp连接并接收消息并回复的线程。实际上我想做的是让用户选择回答是或者不,当线程接受连接时,我的服务类是这样的:
public class Receiver extends Service {
static String TCP_RECEIVE = "soft.b.peopleassist";
public static String ip;
DatagramSocket socket;
private WifiManager.WifiLock wifiLock=null;
private PowerManager.WakeLock wakeLock=null;
volatile public static String outgoingMsg="null";
@SuppressLint("DefaultLocale")
public String getIpAddr() {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ip = wifiInfo.getIpAddress();
String ipString = String.format(
"%d.%d.%d.%d",
(ip & 0xff),
(ip >> 8 & 0xff),
(ip >> 16 & 0xff),
(ip >> 24 & 0xff));
return ipString;
}
private void listenAndWaitAndThrowIntent(Integer port) throws Exception {
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
//ss.setSoTimeout(10000);
//accept connections
Socket s = ss.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//receive a message
String incomingMsg = in.readLine() + System.getProperty("line.separator");
JSONObject jsonObj = new JSONObject();
try {
jsonObj = new JSONObject(incomingMsg);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
String trans=(String) jsonObj.get("TranId");
String ide=(String) jsonObj.get("Amount");
String hashs=(String) jsonObj.get("Basket");
incomingMsg=trans+","+ide+","+hashs;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i("TcpServer", "received: " + incomingMsg);
//send a message
// String outgoingMsg = "goodbye from port " + port + System.getProperty("line.separator");
// outgoingMsg = "ok";
broadcastIntent(incomingMsg);
incomingMsg=null;
Thread.sleep(3000);
out.write(outgoingMsg);
out.flush();
Log.i("TcpServer", "sent: " + outgoingMsg);
broadcastIntent(incomingMsg);
//SystemClock.sleep(5000);
s.close();
outgoingMsg="null";
} catch (InterruptedIOException e) {
//if timeout occurs
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void broadcastIntent(String message) {
Intent intent = new Intent(Receiver.TCP_RECEIVE);
intent.putExtra("messages", message);
sendBroadcast(intent);
}
Thread UDPBroadcastThread;
void startListenForUDPBroadcast() {
UDPBroadcastThread = new Thread(new Runnable() {
public void run() {
try {
// InetAddress broadcastIP = InetAddress.getByName(ip); //172.16.238.42 //192.168.1.255
Integer port = 21111;
while (shouldRestartSocketListen) {
listenAndWaitAndThrowIntent(port);
}
//if (!shouldListenForUDPBroadcast) throw new ThreadDeath();
} catch (Exception e) {
Log.i("UDP", "no longer listening for UDP broadcasts cause of error " + e.getMessage());
}
}
});
UDPBroadcastThread.start();
}
private Boolean shouldRestartSocketListen=true;
void stopListen() {
shouldRestartSocketListen = false;
if(socket!=null)
socket.close();
}
@Override
public void onCreate() {
Log.i("Service", "WiFi lOCK");
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
wifiLock.acquire();
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Lock");
wakeLock.acquire();
};
@Override
public void onDestroy() {
stopListen();
wifiLock.release();
wakeLock.release();
Log.i("UDP", "Service stoped");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
shouldRestartSocketListen = true;
startListenForUDPBroadcast();
Log.i("TCP", "Service started");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
outGoingMsg是实际上是一个响应的消息。现在我希望线程等到线程中这个变量的值没有改变。还有另一个类,我想要改变这个变量。现在我正在调用sleep睡觉这个线程几秒钟,但它不是正确的方式,因为如果几秒后用户没有响应它会自动发送null..please帮助我该怎么做..
答案 0 :(得分:0)
你可以把等待的动作放到一个循环中,如果设置了值就会中断。 出于可见性的原因,您应该使用挥发性修饰符。
我会在一分钟内发布一个例子。
volatile String valueIAmWaitingFor; // Class Variable
...
while(valueIAmWaitingFor == null){
Thread.sleep(3000);
}
//go on
另一种方法现在可以设置valueIAmWaitingFor。
volatile:
声明一个易变的Java变量意味着:此变量的值 永远不会在线程本地缓存:所有读取和写入都将进行 直接“主记忆”;对变量的访问就像它一样 被包含在同步块中,自身同步。
这只是一种方法。有许多更安全的解决方案(但也比此修补程序更复杂)
编辑:当然必须是valueIAmWaitingFor == null
,而不是valueIAmWaitingFor != null