I the code blow.
And I need to call execute within a loop.
Problem is I need the loop to pause while execute is completing and then continue.
The loop runs but it calls execute immediately, which causes the files not be to downloaded.
private class DownloadVerses extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
//Thread.sleep(5000);
if(Utils.downloadFile(params[0])){
int progressPercentage = Integer.parseInt(params[2]);
downloadProgress.setProgress(progressPercentage);
return "Downloading: "+params[1];
}
else{
return "ERROR Downloading: "+params[1];
}
} catch (Exception e) {
Thread.interrupted();
return "ERROR Downloading: "+params[1];
}
}
#Override
protected void onPostExecute(String result) {
if(result.contains("ERROR")){
downloading.setTextColor(Color.parseColor("#f05036"));
}
else{
downloading.setTextColor(Color.parseColor("#79a1ad"));
}
downloading.setText(result);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
And I am currently trying:
DownloadVerses download = new DownloadVerses();
int i = 0;
while(i < verseTitles.size()){
String progressString = String.valueOf(progress);
if(download.getStatus() != AsyncTask.Status.RUNNING){
download.execute(Mp3s.get(i), Titles.get(i),progressString);
if(progress < 100){
if((progress + increment) > 100){
progress = 100;
}
else{
progress += increment;
}
}
i++;
}
}
Remove this line...
DownloadVerses download = new DownloadVerses();
And every time create a new object of DownloadVerses to execute a new AsyncTask...This procedure will not stop any AsyncTask from execution and it will allow every AsyncTask to execute independently.
new DownloadVerses().execute(Mp3s.get(i), Titles.get(i),progressString);
Update your code as follows...
int i = 0;
while(i < verseTitles.size()){
String progressString = String.valueOf(progress);
if(download.getStatus() != AsyncTask.Status.RUNNING){
new DownloadVerses().execute(Mp3s.get(i), Titles.get(i),progressString);
if(progress < 100){
if((progress + increment) > 100){
progress = 100;
}
else{
progress += increment;
}
}
i++;
}
}
Update:
You can use onProgressUpdate() method to update progress update. For more details, you can see AsyncTask document from Android Developer site.
Related
I am dealing with the android UI and I am facing what looks a very common problem here. By using an AsyncTask, I want to:
1- Show a ProgressDialog meanwhile some stuff gets ready
2- Show a countdown to let the user get ready for the real action
3- Play a sound afterwards the countdown to notify the sample will be taken
4- Show another ProgressDialog representing the 10s sample taking
5- Play a sound afterwards the sample is taken
Well, this is my outcome:
1- Works fine
2- MISSING, THE UI IS NOT UPDATED BUT THE BACKGROUND PROCESS IS RUNNING
3- Works fine
4- Works fine
5- Works fine
The funniest is, when I remove the code to handle the first part that handles the first progress dialog, the other parts are executed/displayed as expected. I understand there is something blocking the UI at some point but I am quite newbie with android to realize what's blocking it.
Thanks in advance for your help.
public class SnapshotActivity extends AppCompatActivity {
private int COUNTDOWN_TIME = 5;
private Button startStop;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_snapshot);
startStop = (Button) findViewById(R.id.btnStartStop);
startStop.setText("START");
}
public void startSnapshot(View view) {
startStop.setClickable(false);
new Async(SnapshotActivity.this).execute();
}
class Async extends AsyncTask<Void, Void, Void>{
TextView tv = (TextView) findViewById(R.id.tvCountDown);
ProgressDialog progressDialog ;
ProgressDialog preparing;
Context context;
int flag = 0;
int counter = COUNTDOWN_TIME;
public Async(Context context) {
this.context = context;
progressDialog = new ProgressDialog(context);
preparing = new ProgressDialog(context);
}
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
//PROGRESS DIALOG
flag = 4;
publishProgress();
try {
//SIMULATE SOME WORKLOAD
Thread.sleep(2000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
flag = 5;
publishProgress();
//HANDLE THE COUNTDOWN
for(counter = COUNTDOWN_TIME; counter>=1; counter--){
publishProgress();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
//PLAY THE SOUND
new Thread(new Runnable() {
#Override
public void run() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
}
}).start();
//PROGRESS DIALOG
flag = 1;
publishProgress();
//10s SAMPLE
flag = 2;
for(int j = 0; j <= 10; j++ ){
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
publishProgress();
}
//PLAY THE SOUND
new Thread(new Runnable() {
#Override
public void run() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
}
}).start();
flag = 3;
publishProgress();
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
switch (flag) {
case 0:
tv.setText(String.valueOf(counter));
break;
case 1:
tv.setText("");
progressDialog.setTitle("TAIKING SAMPLE");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMax(10);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
break;
case 2:
progressDialog.incrementProgressBy(1);
break;
case 3:
progressDialog.dismiss();
break;
case 4:
preparing.setMessage("Starting the device...");
preparing.setCanceledOnTouchOutside(false);
preparing.show();
break;
case 5:
preparing.dismiss();
break;
default:
break;
}
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
startStop.setClickable(true);
}
}
}
There are two issues:
You are not informing onProgressUpdate() of the countdown value
There is a race condition
doInBackground() and onProgressUpdate() methods are executed in two different threads and both methods/threads are accessing the flag field in a unsafe way. Instead of setting a value in flag in doInBackground() to be read in onProgressUpdate(), you can inform this value directly in the publishProgress() call. So I advise you to do the following:
public class SnapshotActivity extends AppCompatActivity {
// ...
// Change the Progress generic type to Integer.
class Async extends AsyncTask<Void, Integer, Void> {
// Remove the flag field.
// int flag = 0;
#Override
protected Void doInBackground(Void... params) {
//PROGRESS DIALOG
// Pass the flag argument in publishProgress() instead.
// flag = 4;
publishProgress(4);
// ...
// flag = 5;
publishProgress(5);
//HANDLE THE COUNTDOWN
for (counter = COUNTDOWN_TIME; counter>=1; counter--){
// The countdown progress has two parameters:
// a flag indicating countdown and
// the countdown value.
publishProgress(6, counter);
// ...
}
//PLAY THE SOUND
// ...
//PROGRESS DIALOG
// flag = 1;
publishProgress(1);
//10s SAMPLE
// flag = 2;
for(int j = 0; j <= 10; j++ ){
// ...
publishProgress(2);
}
//PLAY THE SOUND
// ...
// flag = 3;
publishProgress(3);
return null;
}
// This signature changes.
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Redeclare flag here.
int flag = values[0];
switch (flag) {
// ...
case 6:
tv.setText(Integer.toString(values[1]));
break;
// ...
}
}
}
}
My project has a demand, need to constantly read the bar code data, like a commodity supermarket scanner with bar code scanning guns, then data into a keypad, but encountered a problem, for a long time continuously scanning, CPU usage will be very high, even reached 95%, I have set the thread to sleep in a loop, but failed to solve this problem.
I have been asking for this problem, but it may be too messy code, affecting everyone to read, and now simplify the code, I hope you can help me, thank you very much;
Sometimes a few hours on the CPU scan occupy too high, but sometimes a few days there. Grab logcat log found the sleep method sometimes is not executed, if not continuous execution will cause CPU use rate is too high, but I don't know why the sleep method will not perform .
private void startReceive() {
stopReceive = false;
new Thread(new Runnable() {
#Override
public void run() {
int timeout = 1000;
while (!stopReceive) {
if (mUsbDeviceConnection != null) {
try {
byte[] receiveBytes = new byte[64];
int value = mUsbDeviceConnection.bulkTransfer(mUsbEndpoint, receiveBytes,
receiveBytes.length, timeout);
if (value > 0) {
for (int i = 2; !stopReceive && i < receiveBytes.length; i++) {
byte b = receiveBytes[i];
if (b != 0) {
result += new String(new byte[]{b});
}
if (!stopReceive && !result.equals("") && result != null) {
Runtime.getRuntime().exec("input text " + result);
}
}
}
Thread.sleep(100);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}).start();
}
This seemd to be a huge thread running on the main-thread which will drastically slow down the performance of the device.
Big operations you should instead run asynchronously, which means that it will run in the background-thread and not affect the UI-thread which is the issue right now:
Here's a example of how the implementation would look like:
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// StartReceive code..
stopReceive = false;
new Thread(new Runnable() {
#Override
public void run() {
int timeout = 1000;
while (!stopReceive) {
if (mUsbDeviceConnection != null) {
try {
byte[] receiveBytes = new byte[64];
int value = mUsbDeviceConnection.bulkTransfer(mUsbEndpoint, receiveBytes,
receiveBytes.length, timeout);
if (value > 0) {
for (int i = 2; !stopReceive && i < receiveBytes.length; i++) {
byte b = receiveBytes[i];
if (b != 0) {
result += new String(new byte[]{b});
}
if (!stopReceive && !result.equals("") && result != null) {
Runtime.getRuntime().exec("input text " + result);
}
}
}
Thread.sleep(100);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}).start();
return "Done";
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// We're done
}
#Override
protected void onPreExecute() {
// Before starting operation
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
How to start the thread:
LongOperation longOp = new LongOperation();
longOp.execute();
Read more: AsyncTask Android example
You should better look this post and try to find which method consume more system resource: https://stackoverflow.com/a/14688291/6176003
im building an android application that recive images from arduino uno in order to show them continously as a video , i write an asyncTask that reads image and show it in image view , how can i invoke this method every seconed automatically .
here is my asyncTask
I made a button that invoke the async task , but how to make it invoked continously
class myAsyncTask extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
mmInStream = tmpIn;
int byteNo;
try {
byteNo = mmInStream.read(buffer);
if (byteNo != -1) {
//ensure DATAMAXSIZE Byte is read.
int byteNo2 = byteNo;
int bufferSize = 7340;
int i = 0;
while(byteNo2 != bufferSize){
i++;
bufferSize = bufferSize - byteNo2;
byteNo2 = mmInStream.read(buffer,byteNo,bufferSize);
if(byteNo2 == -1){
break;
}
byteNo = byteNo+byteNo2;
}
}
}
catch (Exception e) {
// TODO: handle exception
}
return null;
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
bm1 = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
image.setImageBitmap(bm1);
}
}
If it's from a background thread, one possibility is to use an unbounded for loop. For example, suppose the AsyncTask currently does:
private class MyTask extends AsyncTask<T1, Void, T3>
{
protected T3 doInBackground(T1... value)
{
return longThing(value);
}
protected void onPostExecute(T3 result)
{
updateUI(result);
}
}
then rewrite it as something like:
private class MyTask extends AsyncTask<T1, T3, T3>
{
protected T3 doInBackground(T1... value)
{
for (;;)
{
T3 result = longThing(value);
publishProgress(result);
Thread.sleep(1000);
}
return null;
}
protected void onProgressUpdate(T3... progress)
{
updateUI(progress[0]);
}
}
Of course, you should have a check to break the loop (for example when the Activity is paused or destroyed).
Another option is to create a Handler instance and call postDelayed() repeatedly.
Handler h = new Handler();
h.postDelayed(r, DELAY_IN_MS);
Runnable r = new new Runnable() {
public void run() {
// Do your stuff here
h.postDelayed(this, DELAY_IN_MS);
}
}
I'm trying to show a ProgressDialog when loading an Activity, but it doesn't show up.
Here is the method called on Activity onCreate
private void loadBuilding(String[] b) {
ProgressDialog pd = new ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMax(6);
pd.setTitle(R.string.loading);
pd.show();
LoadBuilding lb = new LoadBuilding();
lb.initialize(this, pd);
lb.execute(b);
try {
lb.get();
} catch (Exception e) {
e.printStackTrace();
}
pd.dismiss();
if (building == null)
showError();
}
The LoadBuilding is an AsyncTask in which I load the building and set the progress.
Thanks to all.
Problem was that the progressDialog.dismiss() must be in:
The catch of the try/catch showed in the code
The onPostExecute method of AsyncTask.
Also I'm using too few data for testing, so it comes up and down too fast.
Use AsyncTask for Background processing and Updating Progressing in Foreground. I think that best suited your task.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Try to add your progressDismiss() in try and catch block
try
{
pg.dismiss();
}
Catch()
{
}
I have created a program in android for multithreading.
When I hit one of the button its thread starts and print value to EditText now I want to determine that thread is running or not so that I can stop the thread on click if it is running and start a new thread if it is not running here is mu code:
public void startProgress(View view) {
final String v;
if(view == b1)
{
v = "b1";
}
else
{
v = "b2";
}
// Do something long
Runnable runnable = new Runnable() {
#Override
public void run() {
//for (int i = 0; i <= 10; i++) {
while(true){
if(v.equals("b1"))
{
i++;
}
else if(v.equals("b2"))
{
j++;
}
try {
if(v.equals("b1"))
{
Thread.sleep(3000);
}
else if(v.equals("b2"))
{
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
// progress.setProgress(value);
if(v.equals("b1"))
{
String strValue = ""+i;
t1.setText(strValue);
}
else
{
String strValue = ""+j;
t2.setText(strValue);
}
//t1.setText(value);
}
});
}
}
};
new Thread(runnable).start();
}
#Override
public void onClick(View v) {
if(v == b1)
{
startProgress(b1);
}
else if(v == b2)
{
startProgress(b2);
}
}
Instead of that messy code, an AsyncTask would do the job you need with added readability ...
It even has a getStatus() function to tell you if it is still running.
You'll find tons of examples by looking around a bit (not gonna write one more here). I'll simply copy the one from the documentation linked above:
Usage
AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)
Here is an example of subclassing:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Once created, a task is executed very simply:
new DownloadFilesTask().execute(url1, url2, url3);
Use a static AtomicBoolean in your thread and flip its value accordingly. If the value of the boolean is true, your thread is already running. Exit the thread if it is true. Before exiting the thread set the value back to false.
There are some way can check the Thread properties
You able to check Thread is Alive() by
Thread.isAlive() method it return boolean.
You able to found runing thread run by
Thread.currentThread().getName()
Thanks