Handler.post() thread, is crashing application - android

I work on an app, which have two activities. MainActivity have to editext in order to send an IP address and Port with Intent, to the second Activity2.
The problem I have is that when I use Handler.post() in order to update TextView in the UI thread, app crashes. Without handler thread app running correctly. I think that my code is correct but I cannot understand the reason for this problem.
public class Activity2 extends Activity {
private Socket s;
private OutputStream out = null;
private PrintWriter w = null;
private Handler handler = new Handler();
private TextView textView1;
private String tag = "ALEX";
private static String IP;
private static int port;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity2);
Bundle extras = getIntent().getExtras();
if (extras != null) {
IP = extras.getString("IP");
String port2 = extras.getString("PORT");
port = Integer.parseInt(port2);
// Log.v("ip",ip);
// Log.v("port",port);
}
Runnable runnable = new Runnable() {
public void run() {
synchronized (this) {
try {
s = new Socket(IP, port);
out = s.getOutputStream();
w = new PrintWriter(out);
} catch (Exception e) {
Log.v("error socket", "Alex soc");
e.printStackTrace();
}
}
**handler.post(new Runnable() {
#Override
public void run() {
synchronized (this) {
try {
Thread.sleep(1000);
if (s.isConnected)
textView1.setText("connected...");
// textView1.setText("not connected...");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
Log.v("error handler", "handler Alex");
e.printStackTrace();
}
}
}
});**
}
};
Thread mythread = new Thread(runnable);
mythread.start();

The problem is that you are creating your handler object once your activity object is created.
Handlers should be created after the Looper is prepared.
so your code should be something like this:
private Handler handler;
private TextView textView1;
private String tag = "ALEX";
private static String IP;
private static int port;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity2);
handler = new Handler();

Related

Android Toast doesn't show

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();
}
});

TextToSpeech stops working after a few hours

I'm trying to make an app reading a string coming from a socket connection, but after a few hours the app stops talking (without exceptions). I'm sure the app is still running because the server sending the string continues to detect the response echo after sending it.
public class MainActivity extends AppCompatActivity {
TextToSpeech textToSpeech;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.ITALY);
}
}
});
Thread socketT = new Thread(new SocketThread());
socketT.start();
}
#Override
public void onDestroy() {
if (textToSpeech != null) {
textToSpeech.stop();
textToSpeech.shutdown();
}
super.onDestroy();
}
private class SocketThread extends Thread {
static final int socketPort = 3333;
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(socketPort);
try {
while(true) {
Socket clientSocket = serverSocket.accept();
try {
new ServerThread(clientSocket);
} catch(IOException e) {
clientSocket.close();
} }
}
catch (IOException e) {
}
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
class ServerThread extends Thread {
private int counter = 0;
private int id = ++counter;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public ServerThread(Socket s) throws IOException {
socket = s;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
out = new PrintWriter(new BufferedWriter(osw), true);
start();
}
public void run() {
try {
while (true) {
String str = in.readLine();
textToSpeech.speak(str, TextToSpeech.QUEUE_FLUSH, null);
}
} catch (IOException e) {}
try {
socket.close();
} catch(IOException e) {}
}
}
}
}
TextToSpeech instance will be available after connect to system service, not after invoke constructor.
So, your plan need to edit like this:
Call TextToSpeech constructor.
Check your TextToSpeech instance is finish to connect to system service through TextToSpeech.OnInitListener.onInit().
Then, connect to your custom service.
Try this as below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
int res = textToSpeech.setLanguage(Locale.ITALY);
if (res >= TextToSpeech.LANG_AVAILABLE) {
// TextToSpeech instance is available after connect to system service!
Thread socketT = new Thread(new SocketThread());
socketT.start();
}
}
}
});
// At this time, your TextToSpeech instance may be not available yet.
//Thread socketT = new Thread(new SocketThread());
//socketT.start();
}

Handling exception - socket connection error and return to previous activity (another thread in another class)

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);
}
});
}
} }

Create thread to run long-work but not responses

thread = new Thread(new Runnable() {
#Override
public void run() {
synchronized (datahandler) {
while (true) {
try {
if (datahandler.getCount() > 0) {
commitData();
}
datahandler.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Log.e("Service", e.toString());
}
}
}
}
});
thread.start();
Commitdata to connect and commit data form datahandler to server. But I dont kow why it shows not respone dialog. If I do not close it, it continouns to commit. Why UI is influenced when I commit data in other thread
public class ThreadsLifecycleActivity extends Activity {
// Static so that the thread access the latest attribute
private static ProgressDialog dialog;
private static Bitmap downloadBitmap;
private static Handler handler;
private ImageView imageView;
private Thread downloadThread;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// create a handler to update the UI
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
imageView.setImageBitmap(downloadBitmap);
dialog.dismiss();
}
};
// get the latest imageView after restart of the application
imageView = (ImageView) findViewById(R.id.imageView1);
Context context = imageView.getContext();
System.out.println(context);
// Did we already download the image?
if (downloadBitmap != null) {
imageView.setImageBitmap(downloadBitmap);
}
// check if the thread is already running
downloadThread = (Thread) getLastNonConfigurationInstance();
if (downloadThread != null && downloadThread.isAlive()) {
dialog = ProgressDialog.show(this, "Download", "downloading");
}
}
public void downloadPicture(View view) {
dialog = ProgressDialog.show(this, "Download", "downloading");
downloadThread = new MyThread();
downloadThread.start();
}
// save the thread
#Override
public Object onRetainNonConfigurationInstance() {
return downloadThread;
}
// dismiss dialog if activity is destroyed
#Override
protected void onDestroy() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
dialog = null;
}
super.onDestroy();
}
static public class MyThread extends Thread {
#Override
public void run() {
try {
// Simulate a slow network
try {
new Thread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
downloadBitmap = downloadBitmap("http://www.devoxx.com/download/attachments/4751369/DV11");
// Updates the user interface
handler.sendEmptyMessage(0);
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
}
//==========================
You can sea in code that handlers are used to post message on GUI thread. further you can read about it over here
http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html
Also Read This http://android-developers.blogspot.de/2010/07/multithreading-for-performance.html

At the time of closing an application: How to stop a thread?

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()
}

Categories

Resources