It is my first time implement horizontal progress bar in my application
The goal is after the progress bar finish, the application show toast message and image bitmap
the toast message is doing fine but the image make the application to force close
this is my code:
Button buttonProceed = (Button) findViewById(R.id.buttonProceed);
buttonProceed.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressBar = new ProgressDialog(v.getContext());
progressBar.setCancelable(true);
progressBar.setMessage("Processing");
progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressBar.setProgress(0);
progressBar.setMax(100);
progressBar.show();
progressBarStatus = 0;
fileProcess = 0;
String toastMessage = "Citra host berhasil ditanam citra watermark dan disimpan di internal storage";
final Toast toast = Toast.makeText(getApplicationContext(), toastMessage, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
final ImageView resultImageView = (ImageView) findViewById(R.id.viewResult);
new Thread(new Runnable() {
public void run() {
while (progressBarStatus < 100) {
progressBarStatus = progressMarker();
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBarHandler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressBarStatus);
}
});
}
if (progressBarStatus >= 100) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar.dismiss();
toast.show();
//the resultBitmap variable is declared in global
resultImageView.setImageBitmap(resultBitmap);
}
}
}).start();
}
});
}
So, could someone help me figure what wrong in my code?
Regard!
The problem is that you aren't allowed to change UI in new Thread. For this purpose you could use AsyncTask instead of Thread.
Here is some example: How to use asynctask to display a progress bar that counts down?
You should call progressBar.setProgress(progressBarStatus); in onProgressUpdate(String... progress) of AsyncTask.
And this code should be called in onPostExecute(String result):
progressBar.dismiss();
toast.show();
//the resultBitmap variable is declared in global
resultImageView.setImageBitmap(resultBitmap);
Because code in onPostExecute is called on main UI Thread.
Related
In the code section given below, I have run a thread on a button click. At first, the thread will set text to the textView, then it will sleep for 6 seconds. But, in reality on the button click, at first, the thread is sleeping for 6 seconds and then it is setting text to the textView. Now, why is this mismatch of statement execution flow happening?
public class MainActivity extends AppCompatActivity {
EditText editText;
Button button;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = findViewById(R.id.editText);
button = findViewById(R.id.button);
textView = findViewById(R.id.textView);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
button.setEnabled(false);
runthread();
}
});
}
private void runthread() {
final String s1 = editText.getText().toString();
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(s1);
button.setEnabled(true);
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
});
}
}
Android main thread is built upon two core concepts Looper and Handler. It translates to a message loop related to the thread, and messages interactor. All the ui staff benefit on that. For instance used by you setText is nothing more then sending a new message to the looper, after some time the message is resolved by some handler. As you may guess firstly each message is enqueued.
If you look at your example through the prism of above, you see steps listed below.(All steps are taken on main thread / main looper)
Handler handler = new Handler(); <-- this handler is related to main looper
handler.post(new Runnable() { <-- enqueue new message to main looper
#Override
public void run() {
runOnUiThread(new Runnable() { <-- enqueue new message
#Override
public void run() {
textView.setText(s1); <-- enqueue new message of setting text
button.setEnabled(true); <-- enqueue new message of enabling button
try {
Thread.sleep(6000); <-- suspend thread for 6 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
});
According to above, you suspend thread before all the messages including setting text and enabling button are handled. The consequence of that is reversed order.
#UPDATE Then, how can I enqueue this sleep() method also?
val handler = Handler();
handler.post {
runOnUiThread {
textView.text = "ABC";
button.isEnabled = true;
}
}
handler.postDelayed({
try {
Thread.sleep(6000);
} catch (e: InterruptedException) {
e.printStackTrace();
}
}, 16) <-- 16 milliseconds is a time between frames
i am trying to make the condition "when the dialog will be dismissed then auto play the video..." with the bellow code , i was accomplished to do that but the videoview doesnt auto play... can you suggest something?
mycode.java
final ProgressDialog progressDialog = new ProgressDialog(PlayVideo.this);
// Set progressbar title
progressDialog.setTitle("Please set the pyramid");
// Set progressbar message
progressDialog.setMessage("Loading...");
// Show progressbar
progressDialog.show();
// Find your VideoView in your video_main.xml layout
myVideoView = (VideoView) findViewById(R.id.video_view);
Uri uri = getIntent().getParcelableExtra("uri");
try {
myVideoView.setMediaController(mediaControls);
myVideoView.setVideoURI(uri);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
myVideoView.requestFocus();
myVideoView.setOnPreparedListener(new OnPreparedListener() {
// Close the progress bar and play the video
public void onPrepared(MediaPlayer mp) {
if(progressDialog.isShowing()) {
Runnable progressRunnable = new Runnable() {
#Override
public void run() {
progressDialog.cancel();
}
};
Handler pdCanceller = new Handler();
pdCanceller.postDelayed(progressRunnable, 3000);
}
if (!progressDialog.isShowing()) {
myVideoView.seekTo(position);
if (position == 0) {
myVideoView.start();
}
else {
myVideoView.pause();
}
}
}
});
}
This will dismiss your dialog once the video is ready and play the video
if (progressDialog.isShowing()) {
Runnable progressRunnable = new Runnable() {
#Override
public void run() {
progressDialog.cancel();
myVideoView.seekTo(position);
if (position == 0) {
myVideoView.start();
} else {
myVideoView.pause();
}
}
};
Handler pdCanceller = new Handler();
pdCanceller.postDelayed(progressRunnable, 3000);
}
I don't know why you are pausing. If you can explain what exactly is the flow that you are trying to implement then I can help better
I've got this code:
#Override
public void onClick(View v) {
progressDoalog = new ProgressDialog(Hack.this);
progressDoalog.setMax(100);
progressDoalog.setMessage("Its loading....");
progressDoalog.setTitle("ProgressDialog bar example");
progressDoalog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDoalog.show();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (progressDoalog.getProgress() <= progressDoalog
.getMax()) {
Thread.sleep(200);
handle.sendMessage(handle.obtainMessage());
if (progressDoalog.getProgress() == progressDoalog
.getMax()) {
progressDoalog.dismiss();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
Handler handle = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progressDoalog.incrementProgressBy(1);
}
};
});
}
}
Where can I add a code to open new activity when the ProgressDialog will be at 100%? Which and where exactly? Thanks for your help!
You can't start an Activity from a Dialog, but what you can do is start the Activity from the old one using a OnDismissListener.
Take a look at the documemtation :
https://developer.android.com/reference/android/content/DialogInterface.OnDismissListener.html
I haven't noticed but you can check the progress in your Handler, check if it's 100%, dismiss the dialog and start the new Activity, remember that you gotta do this on the UI thread
I am trying to play with progress bars. I have this (below) simple activity which runs a progress bar N times one after the other, when I call Progress(N). It is working great but the problem I am facing is, if I press back button. I get into the mainActivity but the progress bars (the threads) are still running in background one after the other. As soon as they finish N loops, the intent is called and whatever I would be doing would be interrupted by this LOOP_OVER activity.
I tried solving this by my own. I tried using variable of Thread class (before I was directly doing it). And tried to interrupt() it at onDestroy() or even just before the intent is called but its not helping. How should I go about it?
public class Loop extends Activity {
private ProgressBar progressBar;
private CircleProgress circleProgress;
private int progressStatus = 0;
private Handler handler = new Handler();
private TextView myView;
private int started = 0, doneLoop=0;
private Thread th;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loop);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
circleProgress = (CircleProgress) findViewById(R.id.circle_progress);
myView = (TextView) findViewById(R.id.instruction);
progressBar.setScaleY(3f);
// Start long running operation in a background thread
Progress(3);
}
#Override
public void onDestroy() {
// Below, everything I am just
th.interrupt();
Loop.this.finish();
Thread.currentThread().interrupt();
super.onDestroy();
}
public void Progress(final int numberOfRuns){
// QueView.setText(Que);
if(numberOfRuns == 0){
th.interrupt();
Intent myIntent = new Intent(Loop.this, LOOP_OVER.class);
startActivity(myIntent);
super.onDestroy();
finish();
}
th = new Thread(new Runnable() {
public void run() {
genNextSet();
while (progressStatus < 100) {
progressStatus += 1;
// Update the progress bar and display the
//current value in the text view
handler.post(new Runnable() {
public void run() {
circleProgress.setProgress(progressStatus);
progressBar.setProgress(progressStatus);
textView.setText(progressStatus+"/"+progressBar.getMax());
}
});
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
myView.setText(Que);
}
});
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
progressStatus = 0;
Progress(numberOfRuns - 1);
}
});
th.start();
}
private void genNextSet() {
// so some cool here!
}
}
You can think of a class variable that is shared among all threads.
Try to add something like this:
private Boolean LOOP = true;
then
while (progressStatus < 100 && LOOP) {
and
#Override
public void onBackPressed() {
LOOP = false
}
also
if(LOOP == true){
// call intent
}
finish();
Your activity does not get destroyed, if you press the "Back"-key, thus onDestroy() will not be called.I'd override onBackPressed(), if I where you.Alternatively, you could try to put it into the onPause()-method.
You haven't override the back button pressed..try this
#Override
public void onBackPressed() {
th.interrupt();
Loop.this.finish();
Thread.currentThread().interrupt();
super.onBackPressed();
// add finish() if you want to kill current activity
}
I'm trying to show a ProgressDialog while I'm processing some data on background.
I call the method show() before starting the Thread, and it doesn't show, but when i call inside the Thread the method dismiss(), it appears and desapears in a flash.
I read some about using an Async Task, but I really don't want to show a progress, just the spinning that ads the user that the app is loading.
How can I solved this?
Some of my code:
// When clicking a button a call this method to start the thread
public void onClick(View v) {
// Here, doesn't show the spinning wheel
progress = ProgressDialog.show(this,
"Wait please …",
"Scanning …",
true);
Thread scan = new Thread(new Runnable() {
#Override
public void run() {
runOnUiThread(new Scanner());
progress.dismiss();
}
});
scan.start();
}
I declared the progress var like this:
private ProgressDialog progress;
public void onCreate(Bundle savedInstanceState) {
//[...]
progress = new ProgressDialog(this);
//[...]
}
The Scanner class code:
private class Scanner implements Runnable {
private final String TAG = "SCANNER-->";
public void run() {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
for (int i = 0; i < 10; i++) {
wifiManager.startScan();
List<ScanResult> results = wifiManager.getScanResults();
if (results != null) {
final int size = results.size();
if (size == 0) {
adapter.clear();
adapter.add("No access points in range");
break;
}
else {
txt.setText("Number of results: " + results.size());
Log.d(TAG,"Number of results: " + results.size());
for (ScanResult result : results) {
if (adapter.getPosition(result.SSID) == -1) {
adapter.add(result.SSID);
}
}
}
}
else {
adapter.clear();
adapter.add("No results. Check wireless is on");
break;
}
adapter.notifyDataSetChanged();
Log.d(TAG,"sistema avisado de cambios");
// Refresh information each 0.5 second
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
progress.dismiss();
}
}
How you can see I'm refreshing a List with nearly networks.
Try this:
progress = ProgressDialog.show(this, "dialog title",
"dialog message", true);
See documentation - static show(...) methods.
http://developer.android.com/reference/android/app/ProgressDialog.html