Android backgroud thread cannot change textview through handler - android

I am unable to understand why my background thread is not able to change the content of textView(txtName) after screen orientation is changed.
If I make txtname as static it works, but without static it does not work. It just has its initial value not getting updated by the background thread.
private TextView txtName;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.screen2);
txtName = (TextView) findViewById(R.id.txtName);
TextView txtEmail = (TextView) findViewById(R.id.txtEmail);
Button btnClose = (Button) findViewById(R.id.btnClose);
Button btnBack = (Button) findViewById(R.id.btnBack);
Intent i = getIntent();
// Receiving the Data
String name = i.getStringExtra("name");
String email = i.getStringExtra("email");
// String data = i.getStringExtra("data");
// Displaying Received data
txtName.setText("HI");
txtEmail.setText(email);
// Binding Click event to Button
btnClose.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
//Closing SecondScreen Activity
Thread background = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
Thread.sleep(1000);
Message msg = new Message();
Bundle b = new Bundle();
b.putString("My Key", "My Value: " + String.valueOf(i));
msg.setData(b);
// send message to the handler with the current message handler
handler.sendMessage(msg);
Log.e("Error", "IN THREAD");
} catch (Exception e) {
Log.d("Error", e.toString());
}
}
}
});
background.start();
}
});
btnBack.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
Intent returnIntent = getIntent();
returnIntent.putExtra("returnResult","i want to back page.");
setResult(RESULT_OK,returnIntent);
finish();
}
});
}
Handler handler = new Handler() {
public void handleMessage(Message msg) {
// get the bundle and extract data by key
Bundle b = msg.getData();
String key = b.getString("My Key");
txtName.setText( "Item " + key);
txtName.setVisibility(View.VISIBLE);
Log.e("TEST MESSAGE", txtName.getText().toString());
}
};

Try runOnUiThread:
#Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
Handler handler = new Handler() {
public void handleMessage(Message msg) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// get the bundle and extract data by key
Bundle b = msg.getData();
String key = b.getString("My Key");
txtName.setText( "Item " + key);
txtName.setVisibility(View.VISIBLE);
Log.e("TEST MESSAGE", txtName.getText().toString());
}
});
}
};
}

Create your OnClickListener as a fixed Class and then apply it as:
MyListener myListener = new MyListener();
btnClose.setOnClickListener(myListener);
In this way the txtName variable musn't be set as final

Your UI can only be updated by the UI thread. Try something like this to ask your UI thread to update the interface as soon as possible. This way i think you can avoid using a handler.
btnClose.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
//Closing SecondScreen Activity
Thread background = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
Thread.sleep(1000);
final String val = "My Value: " + String.valueOf(i);
// ask UI thread to make the changes as soon as possible
txtName.post(new Runnable(){
public void run(){
txtName.setText( "Item " + val);
txtName.setVisibility(View.VISIBLE);
});
} catch (Exception e) {
Log.d("Error", e.toString());
}
}
}
});
background.start();
}
});

Related

Thread dosen't interrupted

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

android, disabling the save button for one hour

i am trying to disable the save button for exactly 1 hour, before the user can save data again. I have come up with some code but since i am still really new to programming i am kind of stuck and any help would be appritiated.
The problem is the button does not lock when i click save.
public void AddData(){
gumb_poslji.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Activity activity = getActivity();
Calendar calander = Calendar.getInstance();
Integer cDay = calander.get(Calendar.DAY_OF_MONTH);
Integer cHour = calander.get(Calendar.HOUR_OF_DAY);
Integer cDayOfTheWeek = calander.get(Calendar.DAY_OF_WEEK)-1;
Integer cMonth = calander.get(Calendar.MONTH)+1;
int seekBarProgressValue = seekBar.getProgress();
String strI = String.valueOf(seekBarProgressValue);
String poslji_data = strI;
boolean pregled_vnosa = myDb.insertData(poslji_data,cHour,cDay,cDayOfTheWeek,cMonth);
if (pregled_vnosa==true)
Toast.makeText(activity, "Vnos uspešen",Toast.LENGTH_LONG).show();
else
Toast.makeText(activity, "Vnos neuspešen!!!",Toast.LENGTH_LONG).show();
}
});
gumb_poslji.setEnabled(true);
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3600000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
gumb_poslji.setEnabled(false);
}
});
}
}).start();
}
Handler mHandler= new Handler();
static Runnable mUpdateTimeTask = new Runnable() {
public void run() {
gumb_poslji.setEnabled(false);
mHandler= .removeCallbacks(mUpdateTimeTask);
}
};
mHandler.postDelayed(this, 3600000);

Using handler to change ui, still "only the original thread that created a view hierarchy can touch its views." error

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

How do I executed a function for specific seconds

So basically, I want to stream data from bluetooth but with on-off mode. Each on & off mode happened for a specific amount of time, i.e 5 seconds.
So,
I need to put a function to executed for a 5 seconds and then executed another function inside a button click method. But my code below doesn't work as it should be.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnOn = (Button) findViewById(R.id.btnOn); // button LED ON
btnOff = (Button) findViewById(R.id.btnOff); // button LED OFF
btnStart = (Button) findViewById(R.id.btnStart);
txtArduino = (TextView) findViewById(R.id.txtArduino); // for display the received data from the Arduino
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
txtArduino.setText("Data from Arduino: " + sbprint); // update TextView
btnOff.setEnabled(true);
btnOn.setEnabled(true);
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapter
checkBTState();
btnOn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
btnOn.setEnabled(false);
bluetoothConnect();
}
});
btnOff.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
btnOff.setEnabled(false);
bluetoothDisconnect();
}
});
btnStart.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
bluetoothDisconnect();
//Starts from here the code doesn't work
//I want to perform these functions over and over
while (true){
//I want method executed for 5 seconds here
h.postDelayed(new Runnable() {
#Override
public void run(){
bluetoothConnect();
}
}, 5000);
//I want method executed for 5 seconds here
h.postDelayed(new Runnable() {
#Override
public void run(){
bluetoothDisconnect();
}
}, 5000);
}
}
});
}
You can try the following way...
private boolean canExecute;
private void callYourMethod() {
canExecute = true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
canExecute = false;
}
}, 5000);
yourMethodToExecuteForFiveSeconds();
}
private void yourMethodToExecuteForFiveSeconds() {
// Your code goes here
if (canExecute) {
//This will be true for five seconds only.
yourMethodToExecuteForFiveSeconds();
}
}

Set time for Custom Dialog

When the user clik on Register Button, a Custom Dialog box appear and the user move to the menu. But in my case, the Costum Dialog appear just for one second and then the user pass to the next layout.
How to set a time for the Custom Dialog please ?
Here my code :
buttonRegister.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
new Thread(new Runnable() {
#Override
public void run() {
final String name = inputName.getText().toString();
final String mail = inputEmail.getText().toString();
final String password = inputPassword.getText()
.toString();
PatientFunctions patientFunction = new PatientFunctions();
json = patientFunction.registerPatient(name, mail,
password);
try {
if (json.getString(KEY_SUCCESS) != null) {
String res = json.getString(KEY_SUCCESS);
if (Integer.parseInt(res) == 1) {
Intent main = new Intent(
getApplicationContext(), Main.class);
main.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(main);
finish();
}
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
catch (JSONException e) {
e.printStackTrace();
}
}
}).start();
CustomizeDialog customizeDialog = new CustomizeDialog(RegisterPatient.this);
customizeDialog.show();
Handler handler = null;
handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
customizeDialog.cancel();
customizeDialog.dismiss();
}
}, 3000);
}
});
There are many good options including AlarmManager, Timer & TimerTask
You can use a handler too like so:
Handler handler = null;
handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
customdialog.cancel();
customdialog.dismiss();
}
}, 500);
the best way to do these kind of process is to use AsyncTask class
and override onPreExecute and doInBackground and onPostExecute
see the official guide
implement the doInBackground() callback method, which runs in a pool of background threads. To update your UI, you should implement onPostExecute(), which delivers the result from doInBackground() and runs in the UI thread, so you can safely update your UI. You can then run the task by calling execute() from the UI thread
private class Registration extends AsyncTask<String, Void, String>{
CustomizeDialog customizeDialog;
#Override
protected void onPreExecute() {
// show ur dialog
customizeDialog = new CustomizeDialog(RegisterPatient.this);
customizeDialog.show();
}
#Override
protected String doInBackground(String... params) {
final String name = params[0];
final String email = params[1];
final String password = params[2];
PatientFunctions patientFunction = new PatientFunctions();
json = patientFunction.registerPatient(name, mail,
password);
try {
if (json.getString(KEY_SUCCESS) != null) {
String res = json.getString(KEY_SUCCESS);
return res;
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
catch (JSONException e) {
e.printStackTrace();
}
}
#Override
protected void onPostExecute(String result) {
if (Integer.parseInt(res) == 1) {
if(customizeDialog != null)
customizeDialog.dismiss();
Intent main = new Intent(
getApplicationContext(), Main.class);
main.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//move to the next activity
startActivity(main);
finish();
}
}
}
Edit
and then execute it what ever you want
buttonRegister.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
final String name = inputName.getText().toString();
final String mail = inputEmail.getText().toString();
final String password = inputPassword.getText()
.toString();
new Registration().execute(name,mail,password);
}
});

Categories

Resources