I have an application that get user input(name and number) , then scanning QR code , and on a press of a button it send the data to my server and get replay from it.
everything is working now as it should.(I can see the message for the server as string when I'm in debug mode).
but I can't see the toast - it doesn't shown
why?
this is the class I have in the ScanActivity.java
public class ScannedBarcodeActivity extends AppCompatActivity {
SurfaceView surfaceView;
TextView txtBarcodeValue;
private BarcodeDetector barcodeDetector;
private CameraSource cameraSource;
private static final int REQUEST_CAMERA_PERMISSION = 201;
Button btnAction;
String intentData = "";
String ServerReply;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan_barcode);
initViews();
}
private void initViews() {
txtBarcodeValue = findViewById(R.id.txtBarcodeValue);
surfaceView = findViewById(R.id.surfaceView);
btnAction = findViewById(R.id.btnAction);
btnAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (intentData.length() > 0) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
String server_ip = "My.Server.Public.IP";
int server_port = 9999;
String messageStr = intentData + "!" + phone +"!"+ name+"!##";
Socket clientSocket = new Socket(server_ip, server_port);
PrintWriter mBufferOut = new PrintWriter((new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()))), true);
BufferedReader mBufferIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
mBufferOut.println(messageStr);
ServerReply = mBufferIn.readLine();
mBufferIn.close();
//see why this is not working - can;t see the toast
Toast.makeText(getApplicationContext(),"inside the thread",Toast.LENGTH_LONG).show();
clientSocket.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
// Toast.makeText(getApplicationContext(),ServerReply,Toast.LENGTH_LONG).show();
thread.start();
}
Toast.makeText(getApplicationContext(),ServerReply,Toast.LENGTH_LONG).show();
SystemClock.sleep(1000); //ms
Toast.makeText(getApplicationContext(),"Going to Main Page now",Toast.LENGTH_LONG).show();
finish();
}
// }
});
}
this is the how it's look after what you told me to do :(still doesn't work , and for some reason it "skip" the toast part)
public class ScannedBarcodeActivity extends AppCompatActivity {
SurfaceView surfaceView;
TextView txtBarcodeValue;
private BarcodeDetector barcodeDetector;
private CameraSource cameraSource;
private static final int REQUEST_CAMERA_PERMISSION = 201;
Button btnAction;
String intentData = "";
boolean isEmail = false;
String ServerReply;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan_barcode);
initViews();
}
private void initViews() {
txtBarcodeValue = findViewById(R.id.txtBarcodeValue);
surfaceView = findViewById(R.id.surfaceView);
btnAction = findViewById(R.id.btnAction);
;
btnAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (intentData.length() > 0) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
String server_ip = "My.Server.IP";
int server_port = 9999;
String messageStr = intentData + "!" + phone +"!"+ name+"!##";
Socket clientSocket = new Socket(server_ip, server_port);
PrintWriter mBufferOut = new PrintWriter((new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()))), true);
BufferedReader mBufferIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
mBufferOut.println(messageStr);
ServerReply = mBufferIn.readLine();
mBufferIn.close();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"inside the thread",Toast.LENGTH_SHORT).show();
}
});
clientSocket.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
thread.start();
}
SystemClock.sleep(1000); //ms
finish();
}
// }
});
}
All the UI rendering should be done on main thread, you can use view handler to do that
v.post(new Runnable(){
Toast.makeText(getApplicationContext(),"inside the thread",Toast.LENGTH_LONG).show();
});
This will execute on UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"inside the thread",Toast.LENGTH_SHORT).show();
}
});
Your toast is coming from a background thread, it needs to be executed on the main/UI thread
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"inside the thread",Toast.LENGTH_LONG).show();
}
});
1) You have to write toast in UI thread. like blow
// you can write toast in UI thread like this
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"inside the thread",Toast.LENGTH_LONG).show();
}
});
2) You have to make sure intentData.length() is not 0 ( if your intentData is empty then your thread will never execute, be sure about that.)
if (intentData.length() > 0) {...}
3) And also make sure your code not given any exception before showing your toast message [handle your exception in catch block like following]
catch (Exception e){
Log.e("Exception","your exception is "+e.toString());
}
Hope it helps you.
Toast can't be run on other than the UI thread, you can use
runOnUiThread(new Runnable() {
#Override
public void run() {
//see why this is not working - can;t see the toast
Toast.makeText(getApplicationContext(),"inside the thread",Toast.LENGTH_LONG).show();
}
});
Related
I'm work on crate server and android client
but thread doesn't interrupted by android client
My android Client has request for the RoomList from server
and Server receive, Client Accept
and fill in my ListView used the Adapter
here's problem if Click backButton,
than RoomListAcitivity was close and thread was stop
but thread dosen't stop just alive in my app
first Enter has work on sucessfully
but Press BackButton on and re-Enter this Activity
MyApp just White, No Action
how can i stop this thread?
(and sorry for my English skill...)
i tried .interrupt() method , and handler.removeMessages(0)
but failed thread keep alive
upload this full java code just in case...
ListView roomList;
RoomAdapter roomAdapter;
Socketservice ss;
String msg,rtitle;
String msgs[];
String list[];
Thread listthread,EnterRoomThread,removeV;
boolean staterun = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_room);
roomList = findViewById(R.id.roomList);
roomAdapter = new RoomAdapter();
listthread = new Thread() {
public void run(){
ss.out.println("163|");
ss.out.println("100|");
try {
while (staterun == true) {
msg = ss.in.readLine();
handler.post(new Runnable() {
public void run() {
msgs = msg.split("\\|");
String protocol = msgs[0];
switch (protocol) {
case "163":
list = msgs[1].split(",");
for (int i = 0; i < list.length; i++) {
String list1[] = list[i].split("-");
String listT = list1[0];
int listC = Integer.parseInt(list1[1]);
int listI = Integer.parseInt(list1[2]);
roomAdapter.CreateRoom(listI, listT, listC);
}
roomList.setAdapter(roomAdapter);
msg = "";
msgs = null;
break;
case "200":
Intent i = new Intent(getApplicationContext(), GameWaitingActivity.class);
i.putExtra("tname", rtitle);
staterun = !staterun;
Toast.makeText(getApplicationContext(),""+listthread.isAlive(),Toast.LENGTH_SHORT).show();
startActivity(i);
finish();
break;
case "201":
Toast.makeText(getApplicationContext(), "방이 꽉 찼습니다.", Toast.LENGTH_SHORT).show();
break;
}
}
});
}
} catch (IOException e) {
}
}
};
listthread.start();
roomList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Room item = (Room) roomList.getItemAtPosition(position);
rtitle=item.getTitle();
EnterRoomThread = new Thread() {
public void run() {
ss.out.println("200|" + rtitle);
EnterRoomThread.interrupt();
}
};
EnterRoomThread.start();
}
});
}
Handler handler = new Handler();
#Override
public void onBackPressed() {
removeV = new Thread() {
public void run(){
ss.out.println("101|");
removeV.interrupt();
}
};
removeV.start();
handler.removeMessages(0);
staterun = false;
listthread.interrupt();
Toast.makeText(getApplicationContext(),""+listthread.isAlive(),Toast.LENGTH_SHORT).show();
finish();
}
}
Go ahead with this, write this inside run() method
//use this boolean value to keep track.
boolean shouldRunFlag = true;
while (shouldRunFlag) {
try {
Thread.sleep(10);
//Do your work............
} catch (Exception e) {
e.printStackTrace();
Log.v(TAG, "Interrupted Exception caught");
// change the flag, so that while loop can be broken.
shouldRunFlag = false;
Log.v(TAG, "run: breaking the loop");
break;
}
}
and this is how you interrupt and clean the thread
private void interrupt(Thread currentThread) {
Log.i(TAG, "interrupt");
if (currentThread != null) {
Thread dummyThread = currentThread;
dummyThread.interrupt();
currentThread = null;
}
}
We have an main activity with a Text View which is requested to auto-retrieve data from TCP server in LAN.
We enabled AsyncTask in updateData() to call Connect to call Handler to update TextView named mTvVoc, and refresh connection by beginConnect().
The problem is the mTvVoc is not updated, it seems the AsyncTask does not function as expected?
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
updateData();
}
public void updateData(final String order) {
Connect(HOST, PORT, order);
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
System.out.println("get data from order--->" + order);
beginConnect(HOST, PORT, order);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}.execute();
}
public String Connect(final String HOST, final int PORT, final String OderType) {
new Thread(new Runnable() {
#Override
public void run() {
try {
socket = new Socket(HOST, PORT);
bufferedInputStream = new BufferedInputStream(socket.getInputStream());
System.out.println("bufferedInputStream--->" + bufferedInputStream);
printWriter = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
if (socket.isConnected()) {
if (!socket.isOutputShutdown()) {
printWriter.println(Integer.toHexString(Integer
.parseInt(OderType)));
}
}
while (true) {
if (!socket.isClosed() && socket.isConnected() && !socket.isInputShutdown()) {
int temp = 0;
byte[] buf = new byte[1024];
while ((temp = bufferedInputStream.read(buf)) != -1) {
isConn(socket);
Log.d("Data received", new String(buf, 0, temp));
acceptinfo = new String(buf, 0, temp);
System.out.println("Data received====》" + acceptinfo);
Message message = new Message();
message.what = 1;
message.obj = acceptinfo;
handler.sendMessage(message);
}
}
}
} catch (UnknownHostException e) {
System.out.println("UnknownHostException-->connection failed");
stopConnect();
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException-->connection failed");
stopConnect();
e.printStackTrace();
}
}
}).start();
return acceptinfo;
}
public String beginConnect(final String HOST, final int PORT, final String OderType) {
new Thread(new Runnable() {
#Override
public void run() {
try {
socket = new Socket(HOST, PORT);
bufferedInputStream = new BufferedInputStream(socket.getInputStream());
System.out.println("bufferedInputStream--->" + bufferedInputStream);
printWriter = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
if (socket.isConnected()) {
if (!socket.isOutputShutdown()) {
printWriter.println(Integer.toHexString(Integer.parseInt(OderType)));
}
}
} catch (UnknownHostException e) {
System.out.println("UnknownHostException-->connection failed");
stopConnect();
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException-->connection failed");
stopConnect();
e.printStackTrace();
}
}
}).start();
return acceptinfo;
}
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i("message", msg.obj.toString());
if (msg.what == 0) {
mIvContent.setImageResource(R.drawable.wangluo_gray);
Toast.makeText(MainActivity.this, "Server connection failed", Toast.LENGTH_SHORT).show();
reGetData();
}
if (msg.what == 1) {
String info = msg.obj.toString();
if (info.length() != 18) {
mIvContent.setImageResource(R.drawable.wangluo_gray);
System.out.println("data verification failed");
reGetData();
return;
}
String iszeroupString = info.substring(1, 3);
String temperature = Integer.toString(Integer.parseInt(info.substring(3, 5), 16));
String vocValue = Integer.toString(Integer.parseInt(info.substring(7, 9), 16));
mTvVoc.setText(getVOC((Integer.valueOf(vocValue ) / 100.00)));
}
}
}
You cannot directly communicate from background thread to UI thread to
update any UI components.
Use this in your background thread to update textview from AsyncTask.
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Log.d("UI thread", "I am the UI thread");
// update your text here
}
});
To update on UI, you need to run the codes in UIThread. See code below and put in your handler:
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.i("message", msg.obj.toString());
if (msg.what == 0) {
mIvContent.setImageResource(R.drawable.wangluo_gray);
Toast.makeText(MainActivity.this, "Server connection failed", Toast.LENGTH_SHORT).show();
reGetData();
}
if (msg.what == 1) {
String info = msg.obj.toString();
if (info.length() != 18) {
mIvContent.setImageResource(R.drawable.wangluo_gray);
System.out.println("data verification failed");
reGetData();
return;
}
String iszeroupString = info.substring(1, 3);
String temperature = Integer.toString(Integer.parseInt(info.substring(3, 5), 16));
String vocValue = Integer.toString(Integer.parseInt(info.substring(7, 9), 16));
mTvVoc.setText(getVOC((Integer.valueOf(vocValue ) / 100.00)));
}
}
});
Pretty bad to code that handler to update the gui. Do away with it as AsyncTask provides already the functionality to do so.
You should have looked better at the many examples.
Use publishProgress() and onProgressUpdate() to update a progress bar and/or other gui elements.
And do not wrap your code in a thread if it has to be executed in doInBackground().
I want to handle the exception of a connection (eg. client has provided incorrect IP address of the server or the server is not listening).
As a result, I want back to previous activity in which in EditText client can change the IP address and then pass it to the next activity using Intent.
public class TcpClient extends Activity {
public static String aHost;
public String aSocketIn;
public static int aSocketInInt;
public Handler uiHandler;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bundle_result);
imageView = (ImageView) findViewById(R.id.imageView);
Intent intent = getIntent();
aHost = intent.getStringExtra("addressIp");
aSocketIn = intent.getStringExtra("socketIn");
aSocketInInt = Integer.parseInt(aSocketIn);
uiHandler = new Handler();
ClientInThread clientInThread = new ClientInThread(aHost,aSocketInInt,uiHandler,imageView);
(new Thread(clientInThread)).start();
} }
class ClientInThread extends Thread implements Runnable {
public Bitmap bitmap = null;
public Handler handler;
String Host;
int SocketIn;
ImageView imageView;
ClientIn clientIn;
Socket socket;
ClientInThread(String Host, int SocketIn, Handler handler, ImageView imageView) {
this.Host = Host;
this.SocketIn = SocketIn;
this.handler = handler;
this.imageView = imageView;
}
public void run() {
try {
InetAddress serwerAddress = InetAddress.getByName(Host);
socket = new Socket(serwerAddress, SocketIn);
clientIn = new ClientIn(socket);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
handler.post(new Runnable() {
#Override
public void run() {
// The following solution has not worked. Error in Intent and startActivity()
Intent intent = Intent(TcpClient.this, MyConnection.class);
startActivity(intent);
// finish();
}
});
}
while(socket.isConnected()) {
bitmap = clientIn.Receive();
if (bitmap == null) {
// Downloading error
return;
}
handler.post(new Runnable() {
#Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
}
} }
I have two threads, two handlers. From thread i check a random number and send result to handle to update ui. But i am getting the error "only the original thread that created a view hierarchy can touch its views.". I searched some articles, they tell to use handler. I am doing that, yet can not avoid the errors.
After some checking, I found that it crashes when A sends the result. In case of B, it works
Also, can i use one handler for two thread?
public class MainActivity extends Activity implements View.OnClickListener{
Button start;
TextView status_B, status_A;
Boolean isRunning;
Thread Athread, Bthread;
int a, b;
Handler a_Handler, b_Handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Initialize variables
start = (Button) findViewById(R.id.button);
start.setOnClickListener(this);
status_B = (TextView) findViewById(R.id.textView);
status_A = (TextView) findViewById(R.id.textView1);
a_Handler = new Handler() {
public void handleMessage(Message msg)
{
int number = msg.getData().getInt("number");
String winner = msg.getData().getString("winner");
start.setEnabled(true);
isRunning = false;
status_A.setText(winner + number);
}
};
b_Handler = new Handler() {
public void handleMessage(Message msg)
{
int number = msg.getData().getInt("number");
String winner = msg.getData().getString("winner");
start.setEnabled(true);
isRunning = false;
status_B.setText(winner + number);
}
};
}
#Override
protected void onStart() {
super.onStart();
isRunning = false;
}
#Override
public void onClick(View v) {
start.setEnabled(false);
status_B.setText("Guessing...");
if (!isRunning)
{
Athread = new Thread(new Runnable() {
#Override
public void run() {
while (isRunning)
{
try
{
Athread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
a = (int) (Math.random()*1000);
System.out.println("a "+ a);
if(a%7 == 0) {
isRunning = false;
Bundle bundle = new Bundle();
bundle.putString("winner", "A");
bundle.putInt("number", a);
Message msg = a_Handler.obtainMessage();
msg.setData(bundle);
a_Handler.handleMessage(msg);
}
}
}
});
Bthread = new Thread(new Runnable() {
#Override
public void run() {
while(isRunning)
{
try
{
Bthread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
b = (int) (Math.random()*1000);
System.out.println("b "+ b);
if(b%7 == 0) {
isRunning = false;
Bundle bundle = new Bundle();
bundle.putString("winner", "B");
bundle.putInt("number", b);
Message msg = b_Handler.obtainMessage();
msg.setData(bundle);
b_Handler.sendMessage(msg);
}
}
}
});
isRunning = true;
Athread.start();
Bthread.start();
}
}
}
You need put your code to modify views on UI thread:
a_Handler = new Handler() {
public void handleMessage(Message msg)
{
final int number = msg.getData().getInt("number");
final String winner = msg.getData().getString("winner");
runOnUiThread(new Runnable() {
#Override
public void run() {
start.setEnabled(true);
status_A.setText(winner + number);
}
});
isRunning = false;
}
};
b_Handler = new Handler() {
public void handleMessage(Message msg)
{
final int number = msg.getData().getInt("number");
final String winner = msg.getData().getString("winner");
runOnUiThread(new Runnable() {
#Override
public void run() {
start.setEnabled(true);
status_B.setText(winner + number);
}
});
isRunning = false;
}
};
I use the following code to receive the data using UDP. When I click the back button my screen visual is closed and it shows the home screen. But a thread is working in the background (it receives the data from the UDP server). When I close the application I also need to stop the thread. How to stop a thread?
public void onClick(View view) {
port=Integer.parseInt(etd_port.getText().toString());
etd_port.setCursorVisible(false);
Thread fst = new Thread(new Server());
fst.start();
}
public class Server implements Runnable {
private String tagid="",roomid="";
public final int SERVERPORT = port;
private DatagramSocket ds;
private String recdata;
#Override
public void run() {
int buffer_size = 1024;
byte buffer[] = new byte[buffer_size];
try {
ds = new DatagramSocket(SERVERPORT);
while (true) {
DatagramPacket p = new DatagramPacket(buffer, buffer.length);
ds.receive(p);
Log.d("MY UDP ","After Receive");
recdata=new String(p.getData(),0,p.getLength());
Log.d("Receive data ",recdata);
}
} catch(Exception e){
Log.e("MY UDP ", " Error", e);
}
}
}
......
#Override
protected void onStop() {
finish();
fst.stop();
super.onStop();
}
You have to change while condition:
class Server implements Runnable {
private boolean running;
public void run() {
running = true;
while (running) {
// do stuff here
}
}
public stop() {
running = false
}
}
protected void onStop() {
fst.stop()
}