I have a custom method of my class that (on my Android phone) takes 2-3 second to finish, and I would like to surround it with a progress bar.
Here is my method:
public void getQuestionsForSelectedCategory(){
ArrayList<Question> temp = (ArrayList<Question>) this.clone();
ArrayList<Question> tempGroup;
this.clear();
for(int i=0;i<2;i++){
tempGroup = new ArrayList<Question>();
for(int j=0;j<temp.size();j++)
if((temp.get(j).getGroup()==i+1)&&(temp.get(j).getCategory().contains(category)||temp.get(j).getCategory().equals("*")))
tempGroup.add(temp.get(j));
getQuestionsForSelectedGroup(tempGroup, numbersByGroup[i], pointsByGroup[i]);
}
tempGroup = new ArrayList<Question>();
for(int i=0;i<temp.size();i++){
int a = temp.get(i).getGroup();
if((a==3||a==4||a==5||a==6||a==7))
if(temp.get(i).getCategory().contains(category)||temp.get(i).getCategory().equals("*"))
tempGroup.add(temp.get(i));
}
Collections.shuffle(tempGroup);
getQuestionsForSelectedGroup(tempGroup, numbersByGroup[2], pointsByGroup[2]);
if(category.equals("C")){
tempGroup = new ArrayList<Question>();
for(int i=0;i<temp.size();i++)
if(temp.get(i).getCategory().equals(category))
tempGroup.add(temp.get(i));
getQuestionsForSelectedGroup(tempGroup, 10, 30);
}
}
And here is what I try to do:
barProgressDialog = new ProgressDialog(this);
barProgressDialog.setTitle("Preparing Test");
barProgressDialog.setMessage("Preparing Test");
barProgressDialog.setProgressStyle(barProgressDialog.STYLE_HORIZONTAL);
barProgressDialog.setProgress(0);
barProgressDialog.setMax(100);
barProgressDialog.show();
new Thread(new Runnable() {
#Override
public void run() {
try {
getQuestionsForSelectedCategory();
while (barProgressDialog.getProgress() <= barProgressDialog.getMax()) {
updateBarHandler.post(new Runnable() {
public void run() {
barProgressDialog.incrementProgressBy(2);
}
});
if (barProgressDialog.getProgress() == barProgressDialog.getMax()) {
barProgressDialog.dismiss();
}
}
} catch (Exception e) {
}
}
}).start();
}
For the current code the progress bar fills up to 100 but it does nothing.
You could use an AsyncTask to achieve this, whilst publishing your progress during the task.
AsyncTask<Void, Integer, Void> task = new AsyncTask<Void, Integer, Void>() {
#Override
protected Void doInBackground(Void... voids) {
getQuestionsForSelectedCategory();
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
barProgressDialog.setProgress(values[0]);
}
#Override
protected void onPostExecute(Void aVoid) {
barProgressDialog.dismiss();
}
}
task.execute();
Ensure your getQuestionsForSelectedCategory and getQuestionsForSelectedGroup methods are inside the AsyncTask and within the loops you can call publishProgress(int progress) to update the progress dialog.
Related
I am trying to show a progress dialog with percentage while executing a long running code, I used AsyncTask for this purpose but it did not work, the functionality is as follow: I get the array paths of all gallery images and then I process these images and extract the descriptor vector of each image and convert it to JSON string and then store these strings into sqlite, but my code takes lot of time( few minutes ), so what I need is to show a progress dialog with percentage in order to know the start and end of the task, this task I need to start it when I press a button. Below is my code:
public void FillDataBase(){
ArrayList<String> paths = getFilePaths();
for (int i = 0; i < paths.size(); i++) {
Mat mat = new Mat();
BitmapFactory.Options bmOptions1 = new BitmapFactory.Options();
//bmOptions1.inSampleSize=4;
Bitmap bitmap0 = BitmapFactory.decodeFile(paths.get(i).toString(), bmOptions1);
Bitmap bitmap = getRotated(bitmap0, paths.get(i).toString());
//Utils.bitmapToMat(bitmap, mat);
Mat matRGB = new Mat();
Utils.bitmapToMat(bitmap, matRGB);
Imgproc.cvtColor(matRGB, mat, Imgproc.COLOR_RGB2GRAY);
org.opencv.core.Size s2 = new Size(3, 3);
Imgproc.GaussianBlur(mat, mat, s2, 2);
FeatureDetector detector2 = FeatureDetector.create(FeatureDetector.ORB);
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
detector2.detect(mat, keypoints2);
DescriptorExtractor extractor2 = DescriptorExtractor.create(DescriptorExtractor.ORB);
Mat descriptors2 = new Mat();
extractor2.compute(mat, keypoints2, descriptors2);
// String matimage = matToJson(mat);
String matkeys= keypointsToJson(keypoints2);
String desc = matToJson(descriptors2);
mat m = new mat(desc, matkeys);
DataBaseHandler db = new DataBaseHandler(getApplicationContext());
db.addmat(m);
}
Asynctask Code (I call the FillDatabase() in public void run of the thread):
private class ProgressTask extends AsyncTask<Void,Void,Void>{
private int progressStatus=0;
private Handler handler = new Handler();
// Initialize a new instance of progress dialog
private ProgressDialog pd = new ProgressDialog(RGBtoGrey.this);
#Override
protected void onPreExecute(){
super.onPreExecute();
pd.setIndeterminate(false);
// Set progress style horizontal
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// Set the progress dialog background color
pd.getWindow().setBackgroundDrawable(new ColorDrawable(Color.YELLOW));
// Make the progress dialog cancellable
pd.setCancelable(true);
// Set the maximum value of progress
pd.setMax(100);
// Finally, show the progress dialog
pd.show();
}
#Override
protected Void doInBackground(Void...args){
// Set the progress status zero on each button click
progressStatus = 0;
// Start the lengthy operation in a background thread
new Thread(new Runnable() {
#Override
public void run() {
FillDataBase();
while(progressStatus < 100){
// Update the progress status
progressStatus +=1;
// Try to sleep the thread for 20 milliseconds
try{
Thread.sleep(20);
}catch(InterruptedException e){
e.printStackTrace();
}
// Update the progress bar
handler.post(new Runnable() {
#Override
public void run() {
// Update the progress status
pd.setProgress(progressStatus);
// If task execution completed
if(progressStatus == 100){
// Dismiss/hide the progress dialog
pd.dismiss();
}
}
});
}
}
}).start(); // Start the operation
return null;
}
protected void onPostExecute(){
// do something after async task completed.
}
And finally i call the Asynctask like this:
testButton0.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new ProgressTask().execute();
}
});
You could do something like this:
private static class InsertAllPersonsToFirebaseTask extends AsyncTask<Void, Float, Void> {
private List<Person> personList;
private ElasticDownloadView mElasticDownloadView;
private DatabaseReference mDatabase, pushedKey;
private Person person;
public InsertAllPersonsToFirebaseTask(List<Person> personList, ElasticDownloadView mElasticDownloadView) {
this.personList = personList;
this.mElasticDownloadView = mElasticDownloadView;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
if (mElasticDownloadView != null) {
this.mElasticDownloadView.setVisibility(View.VISIBLE);
this.mElasticDownloadView.startIntro();
}
}
#Override
protected Void doInBackground(Void... voids) {
mDatabase = FirebaseDatabase.getInstance().getReference();
for (int i = 0; i < personList.size(); i++){
pushedKey = mDatabase.child("Persons").push();
person = new Person();
person.setPersonId(System.currentTimeMillis());
person.setName(personList.get(i).getName());
pushedKey.setValue(person);
//This line is for update the onProgressUpdate() method
publishProgress(((i+1)/(float)personList.size()* 100));
if (isCancelled()){
break;
}
}
return null;
}
#Override
protected void onProgressUpdate(Float... progress) {
if (mElasticDownloadView != null){
mElasticDownloadView.setProgress(progress[0]);
}
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (mElasticDownloadView != null){
mElasticDownloadView.setVisibility(View.GONE);
}
}
}
You can use any type of progressbar. I have used ElasticDownloadview progressbar.
Then:
testButton0.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new InsertAllPersonsToFirebaseTask(personArrayList,mElasticDownloadView).execute();
}
});
I am trying to publish two different kinds of progress in my background process. I am trying to publish a string sometime and an integer another time. I am handling both kinds of arguments in the onProgressUpdate by overloading them too. But when I declare my AsyncTask class, I have the arguments that is why it is expecting me to send only string type arguments. Is there a way to handle both type of publishProgress events?
Basically there are two ways to address your issue:
The first one is very simple, where you just always publishUpdate(String), and then in your onProgressUpdate(String) checks whether the string is an int or a string, and handle each case differently like this:
private class MyAsyncTask extends AsyncTask<Void, String, Void> {
//Executed on main UI thread.
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
try{
Integer i = Integer.parseInt(values[0]);
TextView v1 = (TextView) findViewById(R.id.textView1);
v1.setText(String.valueOf(i));
}
catch(NumberFormatException e){
TextView v2 = (TextView) findViewById(R.id.textView3);
v2.setText(values[0]);
}
}
#Override
protected Void doInBackground(Void... params) {
int i = 0;
while(i < 100){
try {
if(i%2 == 0){
publishProgress("Divisible by 2: " + String.valueOf(i));
}
publishProgress(String.valueOf(i));
i++;
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
}
In the above example I just try and parse the string to an Integer - if it works then I am 100% sure it is an int - if it throws an exception then it is a String.
If you want more control however, you need to implement your own version of AsyncTask, that support one or more progress updates. The only way you can achieve this is by using Handlers (http://developer.android.com/reference/android/os/Handler.html) and Thread (http://developer.android.com/reference/java/lang/Thread.html) directly (preferably wrapped in a more logical class similar to AsyncTask):
import android.os.Handler;
import android.os.Looper;
public abstract class DIYAsyncTask<Params, IntProgress, StringProgress, Result> {
private Result backGroundResult;
//Run on UI thread
#SuppressWarnings("unchecked")
protected void execute(Params... params){
final Params[] thisParams = params;
Thread worker = new Thread(){
public void run(){
prepareForPreExecute();
backGroundResult = doInBackground(thisParams);
prepareForPostExecute();
}
};
worker.setPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
worker.start();
}
//Code to start onPreExecute on UI thread
private void prepareForPreExecute(){
Handler ui_handler = new Handler(Looper.getMainLooper());
ui_handler.post(
new Runnable(){
public void run(){
onPreExecute();
}
}
);
}
//Code to start onPostExecute on UI thread
private void prepareForPostExecute(){
Handler ui_handler = new Handler(Looper.getMainLooper());
ui_handler.post(
new Runnable(){
public void run(){
onPostExecute(backGroundResult);
}
}
);
}
//Always run on worker thread
#SuppressWarnings("unchecked")
protected abstract Result doInBackground(Params... params);
//Always run on UI
protected void onPreExecute(){
}
//Always run on UI
protected void onPostExecute(Result result){
}
//Run on worker
#SuppressWarnings("unchecked")
protected void publishIntProgress(IntProgress... values){
Handler ui_handler = new Handler(Looper.getMainLooper());
final IntProgress[] thisProgress = values;
ui_handler.post(
new Runnable(){
#Override
public void run(){
onIntProgressUpdate(thisProgress);
}
}
);
}
//Always run on UI
#SuppressWarnings("unchecked")
protected void onIntProgressUpdate(IntProgress... values){
}
//Run on worker
#SuppressWarnings("unchecked")
protected void publishStringProgress(StringProgress... values){
Handler ui_handler = new Handler(Looper.getMainLooper());
final StringProgress[] thisProgress = values;
ui_handler.post(
new Runnable(){
#Override
public void run(){
onStringProgressUpdate(thisProgress);
}
}
);
}
//Always run on UI
#SuppressWarnings("unchecked")
protected void onStringProgressUpdate(StringProgress... values){
}
}
Which you can then override like this (notice the similarity to just using AsyncTask)
private class MyDIYAsyncTask extends DIYAsyncTask<Void, Integer, String, Void> {
//Executed on main UI thread.
#Override
protected void onIntProgressUpdate(Integer... values) {
super.onIntProgressUpdate(values);
TextView v = (TextView) findViewById(R.id.textView1);
v.setText(String.valueOf(values[0]));
}
#Override
protected void onStringProgressUpdate(String... values) {
super.onStringProgressUpdate(values);
TextView v = (TextView) findViewById(R.id.textView3);
v.setText(values[0]);
}
#Override
protected Void doInBackground(Void... params) {
int i = 0;
while(i < 100){
try {
publishIntProgress(i);
publishStringProgress("MyString" + String.valueOf(i));
i++;
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
}
Could anyone explain why my progress dialog is not updating when my async task is running?
The progress dialog appears, but the percentage indicator does not increase at all.
Is there something obvious here?
private class DownloadFilesTask extends AsyncTask<ArrayList<String>, Integer, Long> {
private ProgressDialog mProgress;
#Override
protected void onPreExecute()
{
mProgress = new ProgressDialog(HelloActivity.this);
mProgress.setMessage("Fetching Image data..");
mProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgress.setCancelable(false);
//mProgress.setIndeterminate(false);
mProgress.show();
}
#Override
protected Long doInBackground(ArrayList<String>... urls) {
long totalSize = 0;
for(int i=0; i < dbLinks.size(); i++){
try {
....doe some stuff here
publishProgress((i/dbLinks.size()) * 100);
} catch (DbxException e) {
e.printStackTrace();
}
}
return totalSize;
}
#Override
protected void onProgressUpdate(Integer... progress) {
mProgress.setProgress(progress[0]);
}
#Override
protected void onPostExecute(Long result) {
mProgress.dismiss();
//use totalsize if necessary
Intent intentFB = new Intent(HelloActivity.this, PostActivity.class);
intentFB.putExtra("key", dbURLs);
startActivity(intentFB);
}
}
Integer math.
(i/dbLinks.size()) * 100
i/dbLinks.size() will be always 0 and multiplying it by 100 doesn't change it.
To fix it, consider setting progress bar max to dbLinks.size() and publish i as progress.
You may be getting the exception in your doInBackground method ,as i check sample demo it is working fine.
private class DownloadFilesTask extends AsyncTask<String, Integer, Long> {
private ProgressDialog mProgress;
#Override
protected void onPreExecute()
{
mProgress = new ProgressDialog(MainActivity.this);
mProgress.setMessage("Fetching Image data..");
mProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgress.setCancelable(false);
//mProgress.setIndeterminate(false);
mProgress.show();
}
#Override
protected Long doInBackground(String... progress) {
long totalSize = 0;
for(int i=0; i < 100; i++){
try {
publishProgress(i);
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return totalSize;
}
#Override
protected void onProgressUpdate(Integer... progress) {
mProgress.setProgress(progress[0]);
}
#Override
protected void onPostExecute(Long result) {
mProgress.dismiss();
}
}
I want to show a progress dialog while loading some data from remote server :
I'm using the following thread in order to get the data and it's working, but i'm not able to show the progress bar on the activity:
public class Request {
public String text ;
public boolean downloadText(String urlStr) {
final String url = urlStr;
new Thread () {
public void run() {
int BUFFER_SIZE = 2000;
InputStream in = null;
Message msg = Message.obtain();
msg.what=2;
try {
in = openHttpConnection(url);
InputStreamReader isr = new InputStreamReader(in);
int charRead;
text = "";
char[] inputBuffer = new char[BUFFER_SIZE];
while ((charRead = isr.read(inputBuffer))>0)
{
//---convert the chars to a String---
String readString =
String.copyValueOf(inputBuffer, 0, charRead);
text += readString;
inputBuffer = new char[BUFFER_SIZE];
}
Bundle b = new Bundle();
b.putString("text", text);
msg.setData(b);
in.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
would you please tell me how can i do it !!
create the class as below and just call the object of this class.
class MyTask extends AsyncTask<Void, Void, Void> {
ProgressDialog Asycdialog = new ProgressDialog(ActivityName.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
Asycdialog.setMessage("Loading...");
Asycdialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// do the task you want to do. This will be executed in background.
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Asycdialog.dismiss();
}
}
Use progressDialog
final ProgressDialog progress=ProgressDialog.show(youractivity.this,"","message");
new Thread()
{
public void run()
{
try{
youractivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
// your code
}
});
}
catch(Exception e)
{
}
progress.dismiss();
}
}.start()
Also, note that if you want to use Toast, you should use runOnUiThread
If you do not want to change the structure of your code, you can use runOnUiThread or an Handler to show and dissmiss the progress dialog. Show it when the firs line of the run method is excuted and dismiss it in the finally block.
public void run() {
runOnUiThread(new Runnable() {
public void run(){
// show progress dialog
}
});
/// your code here
try {
} catch (IOException e) {
} finally {
runOnUiThread(new Runnable() {
public void run(){
// dismiss progress dialog
}
});
}
}
Create Progress Dialog in AsyncTask
private class YourAsyncTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... args) {
// do background work here
return null;
}
protected void onPostExecute(Void result) {
// do UI work here
}
}
pDialog = ProgressDialog.show(context, null, "Loading...", true);
pDialog.setCancelable(false);
new Thread() {
public void run() {
// handle the exception somehow, or do nothing
// run code on the UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
// do yor ui part here
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}.start();
When user clicks button, will go to Activity B from Activity A.
However, since in Activity B, data will be downloaded from Internet, I would like to add a progress dialog.
Sometimes, the connection will be very fast, less than one second and sometimes will be more than 5 seconds.
If the progress dialog shows <1 sec, I think it is very bad for user experience.
So, I would like to add a minimum loading time, for example, 2 seconds.
That means even the loading time is less than 2 seconds, the progress dialog will also at least show 2 seconds.
Is there any ways to do so?
you can use Below Code. Pass Time and Object of your Dialog here.
public void timerDelayRemoveDialog(long time, final Dialog d){
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
d.dismiss();
}
}, time);
}
EDITED
you can Use this Sample Code :
class LoginProgressTask extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
Thread.sleep(4000); // Do your real work here
} catch (InterruptedException e) {
e.printStackTrace();
}
return Boolean.TRUE; // Return your real result here
}
#Override
protected void onPreExecute() {
showDialog(AUTHORIZING_DIALOG);
}
#Override
protected void onPostExecute(Boolean result) {
// result is the value returned from doInBackground
removeDialog(AUTHORIZING_DIALOG);
Intent i = new Intent(HelloAndroid.this, LandingActivity.class);
startActivity(i);
}
}
My solution (worked well):
private class ProgressTask extends AsyncTask<Void, Void, Void> {
ProgressDialog dialog;
long timestamp1;
long timestamp2;
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(YOUR_CONTEXT);
dialog.setCancelable(false);
dialog.setMessage("Please wait...");
dialog.show();
timestamp1 = System.currentTimeMillis();
}
#Override
protected Void doInBackground(Void... params) {
//doSomething ...
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
//doSomething ...
timestamp2 = System.currentTimeMillis();
long timeDifference = timestamp2 - timestamp1;
if (timeDifference >= 2000) {
dialog.dismiss();
} else {
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
dialog.dismiss();
}
}, 2000 - timeDifference);
}
}
}
Here is another version. Using SystemClock does not require try catch block.
ParentActivity.this is the context where Task is executed.
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.SystemClock;
protected class Task extends AsyncTask< String, Void, String >
{
private ProgressDialog mDialog = new ProgressDialog( ParentActivity.this );
private long mTaskStartTimeMills;
protected void onPreExecute()
{
mTaskStartTimeMills = System.currentTimeMillis();
mDialog.setMessage( "Loading.." );
mDialog.show();
}
protected String doInBackground( String... arg )
{
// TODO
return null;
}
protected void onPostExecute( String json )
{
final long timeToWait = 1000 - ( System.currentTimeMillis() - mTaskStartTimeMills );
if ( timeToWait > 0 )
{
SystemClock.sleep( timeToWait );
}
mDialog.dismiss();
}
}
this may helps you
new AsyncTask<Void, Void, Void>() {
ProgressDialog mDialog;
ArrayList<String> files;
#Override
protected void onPreExecute() {
mDialog = new ProgressDialog(MyMainAct.this);
mDialog.setMessage("Loading");
mDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
// do your work here
Log.i("Share Media MyMainAct", " newFiles is called path is - " + path +"/" + spndirectory.getSelectedItem().toString());
files = getFiles(path + "/" + spndirectory.getSelectedItem().toString());
return null;
}
#Override
protected void onPostExecute(Void result){
if (mDialog != null && mDialog.isShowing()){
mDialog.dismiss();
}
setFileAdapter(files);
}
}.execute();