the changes are not visible in window for vaadin 7 - multithreading

I have a window in vaadin 7, and I would like to show changes as there are made, because I have longer task working its think. I stumble upon this site but I have to move the window to see the changes. In the window that I have, I call next class with :
new PushyUI();
the class called:
public class PushyUI extends UI {
Chart chart = new Chart(ChartType.AREASPLINE);
DataSeries series = new DataSeries();
PushyUI() {
chart.setSizeFull();
setContent(chart);
// Prepare the data display
Configuration conf = chart.getConfiguration();
conf.setTitle("Hot New Data");
conf.setSeries(series);
// Start the data feed thread
new FeederThread().start();
}
class FeederThread extends Thread {
int count = 0;
#Override
public void run() {
try {
// Update the data for a while
while (count < 6) {
Thread.sleep(1000);
getUI().access(new Runnable() {
#Override
public void run() {
double y = Math.random();
series.add(new DataSeriesItem(count++, y),
true, count > 10);
}
});
}
// Inform that we have stopped running
getUI().access(new Runnable() {
#Override
public void run() {
setContent(new Label("Done!"));
}
});
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
How could I see the changes without have to moving the window around ? Thanks

I found the solution here . I manage to modified so it works for me.
layout = new HorizontalLayout();
layout.setSpacing(true);
layout.setSizeFull();
// Add a normal progress bar
sample = new ProgressBar();
layout.addComponent(sample);
layout.setComponentAlignment(sample, Alignment.MIDDLE_CENTER);
startButton = new Button("Start", new Button.ClickListener() {
#Override
public void buttonClick(final ClickEvent event) {
sample.setValue(0f);
sample.setVisible(true);
startButton.setEnabled(false);
UI.getCurrent().setPollInterval(500);
launchProgressUpdater(UI.getCurrent(), 10);
}
});
startButton.setStyleName(ValoTheme.BUTTON_SMALL);
layout.addComponent(startButton);
layout.setComponentAlignment(startButton, Alignment.MIDDLE_CENTER);
...
private void launchProgressUpdater(UI ui, int maxProgress) {
new Thread(() -> {
for (int progress = 1; progress <= maxProgress; progress++) {
try {
Thread.sleep(1000);
} catch (final InterruptedException e) {
throw new RuntimeException("Unexpected interruption", e);
}
updateProgressBar(ui, progress, maxProgress);
}
}).start();
}
private void updateProgressBar(UI ui, int progress, int maxProgress) {
ui.access(() -> {
final float newValue;
if (progress == maxProgress) {
ui.setPollInterval(-1);
startButton.setEnabled(true);
newValue = 0f;
sample.setVisible(!sample.isIndeterminate());
} else {
newValue = (float) progress / maxProgress;
}
sample.setValue(newValue);
Notification.show("Value changed:", Float.toString(newValue), Notification.Type.TRAY_NOTIFICATION);
});
}

Related

Can't send more than 160 byte to module by Bluetooth on Android?

Unable to send more than 160 bytes to a Bluetooth (BLE) module from my Android application, I am sending data from my modified Fastble Android app to a microchip RN4871 Bluetooth. I'm running BLE in transparent UART mode. After connecting to the module, In Android application, calling a notify function and then a write function to send packets in 20-byte chunks.
However, after 160 bytes, the Android application does not send any more data; by increasing MTU, we can send up to 600 bytes but no more.
What we basically observed is that after we modified the Fastble android code, the notify descriptor has a NULL value, which we are unable to correct because I did not understand the cause.
this is the calling code for notify and write function, "hex" variable is the string to write.
<code>
setCharaProp(2);
((CharacteristicOperationFragment) fragments.get(2)).showData(hex);
setCharaProp(1);
((CharacteristicOperationFragment) fragments.get(2)).showData(hex);
setCharaProp(2);
<code>
the below code is to notify and write
<code>
public void showData(String hex) {
final BleDevice bleDevice = ((OperationActivity) getActivity()).getBleDevice();
final BluetoothGattCharacteristic characteristic = ((OperationActivity) getActivity()).getCharacteristic();
final int charaProp = ((OperationActivity) getActivity()).getCharaProp();
String child = characteristic.getUuid().toString() + String.valueOf(charaProp);
for (int i = 0; i < layout_container.getChildCount(); i++) {
layout_container.getChildAt(i).setVisibility(View.GONE);
}
if (childList.contains(child)) {
layout_container.findViewWithTag(bleDevice.getKey() + characteristic.getUuid().toString() + charaProp).setVisibility(View.VISIBLE);
} else {
childList.add(child);
View view = LayoutInflater.from(getActivity()).inflate(R.layout.layout_characteric_operation, null);
view.setTag(bleDevice.getKey() + characteristic.getUuid().toString() + charaProp);
LinearLayout layout_add = (LinearLayout) view.findViewById(R.id.layout_add);
final TextView txt_title = (TextView) view.findViewById(R.id.txt_title);
txt_title.setText(String.valueOf(characteristic.getUuid().toString() + getActivity().getString(R.string.data_changed)));
final TextView txt = (TextView) view.findViewById(R.id.txt);
txt.setMovementMethod(ScrollingMovementMethod.getInstance());
switch (charaProp) {
case PROPERTY_WRITE:
{
View view_add = LayoutInflater.from(getActivity()).inflate(R.layout.layout_characteric_operation_et, null);
if (TextUtils.isEmpty(hex)) {
return;
}
BleManager.getInstance().write(
bleDevice,
characteristic.getService().getUuid().toString(),
characteristic.getUuid().toString(),
HexUtil.hexStringToBytes(hex),
new BleWriteCallback() {
#Override
public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
runOnUiThread(new Runnable() {
#Override
public void run() {
addText(txt, "write success, current: " + current +
" total: " + total +
" justWrite: " + HexUtil.formatHexString(justWrite, true));
}
});
}
#Override
public void onWriteFailure(final BleException exception) {
runOnUiThread(new Runnable() {
#Override
public void run() {
addText(txt, exception.toString());
}
});
}
});
layout_add.addView(view_add);
}
break;
case PROPERTY_NOTIFY:
{
View view_add = LayoutInflater.from(getActivity()).inflate(R.layout.layout_characteric_operation_button, null);
if (my_notify_ctl == 1) {
my_notify_ctl = 0;
BleManager.getInstance().notify(
bleDevice,
characteristic.getService().getUuid().toString(),
characteristic.getUuid().toString(),
new BleNotifyCallback() {
#Override
public void onNotifySuccess() {
runOnUiThread(new Runnable() {
#Override
public void run() {
addText(txt, "notify success");
}
});
}
#Override
public void onNotifyFailure(final BleException exception) {
runOnUiThread(new Runnable() {
#Override
public void run() {
addText(txt, exception.toString());
}
});
}
#Override
public void onCharacteristicChanged(byte[] data) {
runOnUiThread(new Runnable() {
#Override
public void run() {
addText(txt, HexUtil.formatHexString(characteristic.getValue(), true));
}
});
}
});
} else {
BleManager.getInstance().stopNotify(
bleDevice,
characteristic.getService().getUuid().toString(),
characteristic.getUuid().toString());
my_notify_ctl = 1;
}
layout_add.addView(view_add);
}
break;
layout_container.addView(view);
}
}
<code>

JavaFX FX application Thread Issue

I'm doing a desktop application and I'm performing a heavy task in background. I want a progress bar to be updated. My program works and I can see the progress bar here isn't my problem. My problem is that I use 2 tasks that I run in 2 thread in order to make both the update of the progress bar and the heavy task. My question is : Is there a better way to do in oder to avoid the error "Exception in thread "Thread-5" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5".
Of course I already check on Internet and I always find : better use Platform.runLater. Ok but in both new thread I need attribute of my class, eg I can't access for example "this.myAttribute" when I use Platform.runLater((new Runnable()...)). Is RunLater the solution and I can't see it ?
Here is a bunch of code, the method setConnection is called in JavaFX thread, and I create 2 other. One for progressbar, the other for my task :
#FXML
private void setConnection() {
try {
this.onOffButton.setSelected(false);
if (!this.hubModel.isConnected()) {
this.progressBar.progressProperty().unbind();
#SuppressWarnings("unchecked")
OperationTask progressBarOperationTask = new OperationTask(this) {
#Override
public Void call() {
HubController hubController = (HubController) this.getHubController();
hubController.getProgressBar().setVisible(true);
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(25);
} catch (InterruptedException e) {
Thread.interrupted();
break;
}
updateProgress(i + 1, 100);
}
hubController.getProgressBar().setVisible(false);
return null;
}
};
this.progressBar.progressProperty().bind(progressBarOperationTask.progressProperty());
Thread timeThread = new Thread(progressBarOperationTask);
timeThread.setDaemon(true);
timeThread.start();
}
#SuppressWarnings("unchecked")
OperationTask connectionOperationTask = new OperationTask(this) {
#Override
protected Object call() throws Exception {
HubController hubController = (HubController) this.getHubController();
if (hubController.getUserID().getText().equals("") || hubController.getUserPW().getText().equals("")) {
hubController.getCommentBottom().setText("Please enter a user name and a password.");
hubController.getOnOffButton().setSelected(false);
} else {
hubController.getHubModel().setIdUser(hubController.getUserID().getText());
hubController.getHubModel().setPwUser(hubController.getUserPW().getText());
String comment = hubController.getHubModel().setConnection();
if (!comment.equals("Connection established.")) {
hubController.getOnOffButton().setSelected(false);
}
if (hubController.getHubModel().isConnected()) {
hubController.getConnectionStatus().setText("Connected");
hubController.getConnectionStatus().setStyle("-fx-font-weight: bold");
String commentProject = hubController.getHubModel().getAllProjects();
if (commentProject.equals("")) {
TextFields.bindAutoCompletion(hubController.getCloneAndMoveController().getNewProjectNameTextField(), hubController.getHubModel().getProjectsList());
} else {
comment = commentProject;
}
hubController.getOnOffButton().setSelected(true);
} else {
hubController.getConnectionStatus().setText("Not connected");
hubController.getConnectionStatus().setStyle("-fx-font-weight: regular");
}
hubController.getCommentBottom().setText(comment);
}
return null;
}
};
Thread connectionThread = new Thread(connectionOperationTask);
connectionThread.setDaemon(true);
connectionThread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
Moreover if you see something that could be improved, I would appreciate (I'm new with java)
Thank you.
You can access your object from Platform.runLater(). New Runnable which you create for it has access to this instance of your object. See in an example:
private String myAttribute = "hello";
#Override
public void randomMethod() {
//...
Platform.runLater(new Runnable() {
#Override
public void run() {
System.out.println(myAttribute);
}
});
}

Download File using download manager and save file based on click

I have my download manager, and it work perfect if I try to download a file. But I have a problem.
I have 4 CardView in my activity and I set it onClickListener, so when I click one CardView it will download the file.
Here is the code to call the download function
cardviewR1 = findViewById(R.id.card_viewR1);
cardviewR1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pDialogDL = new ProgressDialog(this);
pDialogDL.setMessage("A message");
pDialogDL.setIndeterminate(true);
pDialogDL.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialogDL.setCancelable(true);
final DownloadTask downloadTask = new DownloadTask(this);
downloadTask.execute(R1Holder);
pDialogDL.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
}
});
and here is the download function
private class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
private PowerManager.WakeLock mWakeLock;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/"+getString(R.string.r1)+"_"+NameHolder+".zip");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled()) {
input.close();
return null;
}
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
// take CPU lock to prevent CPU from going off if the user
// presses the power button during download
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
mWakeLock.acquire();
pDialogDL.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
// if we get here, length is known, now set indeterminate to false
pDialogDL.setIndeterminate(false);
pDialogDL.setMax(100);
pDialogDL.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
mWakeLock.release();
pDialogDL.dismiss();
if (result != null)
Toast.makeText(context, "Download error: " + result, Toast.LENGTH_LONG).show();
else
Toast.makeText(context, "File downloaded", Toast.LENGTH_SHORT).show();
}
}
The code work in my app, but the problem is, when I try to add second CardView which is like this
cardviewR2 = findViewById(R.id.card_viewR2);
cardviewR2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pDialogDL = new ProgressDialog(this);
pDialogDL.setMessage("A message");
pDialogDL.setIndeterminate(true);
pDialogDL.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialogDL.setCancelable(true);
final DownloadTask downloadTask = new DownloadTask(this);
downloadTask.execute(R2Holder);
pDialogDL.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
}
});
Yes it will download the second file, but it will overwrite the first file. I think the problem is right here
output = new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/"+getString(R.string.r1)+"_"+NameHolder+".zip");
Anyone can help me with this code?
I need your help, Thanks
Fixed it by create a new Download Class separately in different file with activity, so the AsyncTask will be call again and again
thanks

javafx background tasks: call service in another service

I Would like to execute a background task which executes multiple background tasks. What i am actually trying to do is execute a background process which executes some code for every Object in a list, and does it within a fixed thread pool. So, for example, i have 100 users in the list and i am executing code for each of them concurrently but no more than 5 at the same time.
Therefore i am using two service/task pairs: One service/task for executing on the whole list of users, this service uses a fixed thread pool as its executor and executes a series of second service/task pairs for every user in the list.
like in the following example:
class MainService extends Service<List<User>> {
private List<User> users;
public MainService(List<User> users) { this.users=users; }
protected Task<List<User>> createTask(){
return new MainTask(this.users)
}
}
class Maintask extends Task<List<User>> {
private List<User> users;
private Executor executor;
public MainTask(List<User> users) {
this.users=users;
this.executor=Executors.newFixedThreadPool(5);
}
protected List<User> call() throws Exception {
for (User user : this.users) {
System.out.println("Starting single service");
SingleService service=new SingleService(user)
service.setExecutor(this.executor);
service.start();
System.out.println("Single service started");
}
}
}
class SingleService extends Service<User> {
private User user;
public SingleService(User user) { this.user=user; }
protected Task<User> createTask() {
return new SingleTask(this.user)
}
}
class SingleTask extends Task<User> {
private User user;
public SingleTask(User user) { this.user=user; }
protected User call() throws Exception() {
// Do some work
}
}
The code executes up to the moment when first "starting single service" is printed, the "single service started" message is not being printed at all. As far as i see the SingleService is started, but its createTask() is not being executed at all. Am i making some mistake here?
Well, I am trying to do the same thing, in different context... launch multiple services from a single main Service.
I've overridden all methods of Service, and this is my printout:
Service must only be used from the FX Application Thread {from onFailed() method}
Service does not run on FX thread, but can only be called from the FX thread.
Therefore, all Services and Tasks called within a Service or Task will not be executed.
This is my work around:
public class FXComponentImporter extends Service<Void> implements JarImporter {
//Scanner<T> = Service<List<Class<T>>>
private Scanner<Node> nodeScanner = null;
private Scanner<Paint> paintScanner = null;
private Scanner<Animation> animationScanner = null;
private static int nodeCount = 0, paintCount = 0, animationCount = 0;
private final ObservableMap<String, Class<?>> foundComponents = FXCollections.observableHashMap();
public FXComponentImporter() {
this(null);
}
public FXComponentImporter(File file) {
if (file != null) {
try {
this.nodeScanner = new Scanner<>(file, Node.class);
this.paintScanner = new Scanner<>(file, Paint.class);
this.animationScanner = new Scanner<>(file, Animation.class);
} catch (IOException ex) {
Logger.getLogger(FXComponentImporter.class.getName()).log(Level.SEVERE, null, ex);
}
} else {
File f = importJar();
try {
this.nodeScanner = new Scanner<>(f, Node.class);
this.paintScanner = new Scanner<>(f, Paint.class);
this.animationScanner = new Scanner<>(f, Animation.class);
} catch (IOException ex) {
Logger.getLogger(FXComponentImporter.class.getName()).log(Level.SEVERE, null, ex);
}
}
this.scanningDone.bind(this.nodeScanningDone.and(this.paintScanningDone.and(this.animationScanningDone)));
this.scanningDone.addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue) {
if(scanningDone.isBound()){
scanningDone.unbind();
}
start();
scanningDone.removeListener(this);
}
}
});
startScanning();
}
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
Map<String, Class<?>> map = new HashMap<>();
List<Class<Node>> nodes = new ArrayList<>();
List<Class<Paint>> paints = new ArrayList<>();
List<Class<Animation>> anims = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(1);
//Platform needed due to Service only accessed from FX thread
Platform.runLater(() -> {
try {
//FX Stuff done here
nodes.addAll(nodeScanner.getMatchingClasses());
paints.addAll(paintScanner.getMatchingClasses());
anims.addAll(animationScanner.getMatchingClasses());
} finally {
latch.countDown();
}
});
latch.await();
this.updateMessage("Scanning for Nodes ... ");
nodes.stream().forEach(n -> {
if(n != null){
map.putIfAbsent(n.getSimpleName(), n);
}
nodeCount++;
});
this.updateMessage("Found : " + nodeCount + " Nodes ... ");
this.updateMessage("Scanning for Paints ... ");
paints.stream().forEach(p -> {
if(p != null){
map.putIfAbsent(p.getSimpleName(), p);
}
paintCount++;
});
this.updateMessage("Found : " + paintCount + " Paints ... ");
this.updateMessage("Scanning for Animations ... ");
anims.stream().forEach(a -> {
if(a != null){
map.putIfAbsent(a.getSimpleName(), a);
}
animationCount++;
});
this.updateMessage("Found : " + animationCount + " Animations ... ");
foundComponents.putAll(map);
return null;
}
};
}
#Override
protected void executeTask(Task<Void> task) {
super.executeTask(task);
System.out.println(getClass().getSimpleName() + " is Executing " + task.getTitle());
}
#Override
protected void cancelled() {
super.cancelled();
System.out.println(getClass().getSimpleName() + " was Cancelled ... ");
}
#Override
protected void running() {
super.running();
System.out.println(getClass().getSimpleName() + " is Running ... ");
}
#Override
protected void ready() {
super.ready();
System.out.println(getClass().getSimpleName() + " is Ready! ... ");
}
#Override
protected void scheduled() {
super.scheduled();
System.out.println(getClass().getSimpleName() + " is Scheduled ... ");
}
#Override
protected void failed() {
super.failed();
System.out.println(getException().getMessage());
}
#Override
protected void succeeded() {
super.succeeded();
System.out.println("Importing Succeeded ... with: " + foundComponents.entrySet().size() + " results.\n");
foundComponents.forEach((s, c) -> {
System.out.println(c.getSuperclass().getSimpleName() + " >> " + s + " : " + c.getSimpleName());
});
}
#Override
public void restart() {
super.restart();
System.out.println(getClass().getSimpleName() + " is Restarting ... ");
}
private void startScanning() {
nodeScanner.stateProperty().addListener(nsl);
paintScanner.stateProperty().addListener(psl);
animationScanner.stateProperty().addListener(asl);
nodeScanner.start();
paintScanner.start();
animationScanner.start();
}
private final BooleanProperty scanningDone = new SimpleBooleanProperty(false);
private final BooleanProperty nodeScanningDone = new SimpleBooleanProperty(false);
private final BooleanProperty paintScanningDone = new SimpleBooleanProperty(false);
private final BooleanProperty animationScanningDone = new SimpleBooleanProperty(false);
private final ChangeListener nsl = new ChangeListener<Worker.State>() {
#Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
if (newValue.equals(State.SUCCEEDED)) {
nodeScanningDone.set(true);
nodeScanner.stateProperty().removeListener(this);
}
}
};
private final ChangeListener psl = new ChangeListener<Worker.State>() {
#Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
if (newValue.equals(State.SUCCEEDED)) {
paintScanningDone.set(true);
paintScanner.stateProperty().removeListener(this);
}
}
};
private final ChangeListener asl = new ChangeListener<Worker.State>() {
#Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
if (newValue.equals(State.SUCCEEDED)) {
animationScanningDone.set(true);
animationScanner.stateProperty().removeListener(this);
}
}
};
public ObservableMap<String, Class<?>> getFoundComponents() {
return foundComponents;
}
}
and my Interface if you wanna try it out:
public interface JarImporter {
public static File defaultDirectory = new File(System.getProperty("user.home"));
public static final FileChooser.ExtensionFilter classfilter = new FileChooser.ExtensionFilter("Jar files", "*.jar");
static FileChooser defaultFileChooser(){
FileChooser fc = new FileChooser();
fc.getExtensionFilters().add(classfilter);
fc.setInitialDirectory(defaultDirectory);
return fc;
}
public default File importJar(){
File jar = defaultFileChooser().showOpenDialog(null);
if(jar != null){
return jar;
}else{
return null;
}
}
}
Hope this helps.. though just looked at Question date, and was a while ago...

How to enable a button after 5 seconds

everyone! I need to make a Button disabled for 5 seconds, and the caption of the button must be "Skip" plus the time the button will stay disabled.
I have made a class CTimer that extends Thread, and defined the run method with run(Button). The run method receives the Button which Caption will be modified and is as follows:
public void run(Button skip){
for ( int i=5; i<0; i--)
{
skip.setText("Skip (" + i + ")");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
skip.setEnabled(true);
}
The problem is that the code does not work, any thouhts, anyone?
I have tried the following code & it works fine for me:
public class Main_TestProject extends Activity
{
private Button b;
private int index = 5;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b = (Button) findViewById(R.id.my_button);
b.setEnabled(false);
hHandler.sendEmptyMessage(0);
}
private Handler hHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if(index > 0)
{
try
{
b.setText("Skip (" + String.valueOf(index) + ")");
index--;
Thread.sleep(1000);
hHandler.sendEmptyMessage(0);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
b.setEnabled(true);
}
}
};
}

Resources