This is a little XML animation that I'm trying to get to go off while the app is getting JSON from the server. It takes about 2 seconds to fetch all the data so I'm trying to show a little loading animation.
The problem I am having is that the images do not change until everything is done and onPostExecute() goes off.
Do I need to pass a view into the AsyncTask or is it something else?
One last thing after this AsyncTask completes. It runs smooth if you run it again.
XML
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="#drawable/loadingtext1" android:duration="100" />
<item android:drawable="#drawable/loadingtext2" android:duration="100" />
<item android:drawable="#drawable/loadingtext3" android:duration="100" />
<item android:drawable="#drawable/loadingtext4" android:duration="100" />
</animation-list>
Code
private class LOGMEIN extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
CRY.CInit(DI, DU, DP);
publishProgress(0);
while(data != "whatineed"){
try {
Thread.sleep(450);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
completecheck = 1;
return "complete";
}
#Override
protected void onPreExecute() {
LOADINGTEXT.setBackgroundResource(R.drawable.animation);
AnimationDrawable LT = (AnimationDrawable) LOADINGTEXT.getBackground();
LT.start();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result.contentEquals("complete") == true) {
domorework();
} else {
finish();
}
}
}
Have you set onPreExecute() within the AsyncTask?
protected void onPreExecute() {
//show your animated loader here...
progress.show();
}
I use this in onCreate():
Initialize: public ProgressDialog progress;
progress = new ProgressDialog(this);
progress.setCancelable(true);
progress.setInverseBackgroundForced(false);
progress.setCanceledOnTouchOutside(true);
progress.setMessage("Loading.....");
I don't know if this is the only problem but you are comparing your Strings wrong in your loop.
while (data != "whatineed")
should be
while (!data.equals("whatineed"))
or even better would be
while (!"whatineed".equals(data))
to compare the values instead of the object reference
Related
Hope all are playing well with Errors.
I am stuck with silly problem. I don't know why it is happening?
I have created one AsyncTask in that i am doing process of uploading images.
/**
* Uploading Images
*/
private class UploadPhotosTask extends AsyncTask<Void, Integer, Integer> {
String errorMessage;
ArrayList<PhotoCaption> captionArrayList;
private ProgressDialog progressDialog;
private UploadPhotosTask(ArrayList<PhotoCaption> arrayList) {
captionArrayList = arrayList;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(AlbumPhotoDetailsActivity.this);
progressDialog.setTitle("Wait for a while");
progressDialog.setMessage("Uploading Photos...");
progressDialog.setIndeterminate(true);
progressDialog.setProgress(0);
progressDialog.setMax(captionArrayList.size());
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressDialog.setProgress(values[0]);
}
#Override
protected Integer doInBackground(Void... params) {
//Processing for upload
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
progressDialog.dismiss();
}
}
It doesn't showing Title or Message, I dont know why.
Note: I have tried all the possibilities. If i remove
setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) it is displaying
circular progress but i want here Horizontal ProgressBar with Number
of Images which are ready to upload.
Any Idea? Why It is so? Your help would be appreciated. Thank you.
It is theme issue on your end,probably textcolor set to white in your theme change these
<item name="android:textColorPrimary">#color/white</item>
<item name="android:textColorSecondary">#color/white</item>
change it to black
Its all about theme problem as i have defined in my style.xml
<item name="android:textColorPrimary">#color/colorPrimaryText</item>
<item name="android:textColorSecondary">#color/colorSecondaryText</item>
where colorPrimaryText have white color. I have just removed that lines.
I want to display a progressbar when my activity load. But the progressbar work only half the time and when the progressbar doesn't work a black screen was display while charging.
This is my AsyncTask:
class Task extends AsyncTask<String, Integer, Boolean> {
#Override
protected void onPreExecute() {
layout.setVisibility(View.VISIBLE);
titre_projet.setVisibility(View.GONE);
description_projet.setVisibility(View.GONE);
image_projet.setVisibility(View.GONE);
super.onPreExecute();
}
#Override
protected void onPostExecute(Boolean result) {
layout.setVisibility(View.GONE);
titre_projet.setVisibility(View.VISIBLE);
description_projet.setVisibility(View.VISIBLE);
image_projet.setVisibility(View.VISIBLE);
super.onPostExecute(result);
}
#Override
protected Boolean doInBackground(String... params) {
try {
runOnUiThread(new Runnable() {
public void run() {
Intent intent = getIntent();
if (intent != null) {
searchResultats(intent.getStringExtra(EXTRA_PROJET));
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
In this code, all in runOnUiThread is my code to display the content.
This is what I have in OnCreate:
image_projet = (ImageView) findViewById(R.id.imageView_projet);
layout = (LinearLayout) findViewById(R.id.progressbar_view);
titre_projet = (TextView) findViewById(R.id.titre_projet);
description_projet = (TextView) findViewById(R.id.description_projet);
new Task().execute();
And my XML for the progressBar:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%" android:pivotY="50%" android:fromDegrees="0"
android:toDegrees="360"
android:layout_width="match_parent"
android:layout_height="match_parent">
<shape android:shape="ring" android:innerRadiusRatio="3"
android:thicknessRatio="8" android:useLevel="false">
<size android:width="76dip" android:height="76dip" />
<gradient android:type="sweep" android:useLevel="false"
android:startColor="#447a29"
android:endColor="#447a29"
android:angle="0"
/>
</shape>
</rotate>
When your News Activity starts, start to fetch your data (article). In the onCreate method of Activity, start your task. In the doInBackground method of your Task, fetch the article (I assume you'll need to fetch it through network).
Once your Task is done, update your UI in onPostExecute.
class Task extends AsyncTask<String, Integer, Object> {
private Activity activity;
public Task(Activity a){
activity=a;
}
#Override
protected void onPostExecute(Object article) {
activity.onArticleFetched(article);
}
#Override
protected Object doInBackground(String... params) {
Object article = new Article();
//Fetch article... may take a few seconds, but you don't care because you are not in the UI thread
return article;
}
}
In the Activity, do something like this :
class NewsActivity extends Activity {
#Override
public void onCreate(Bundle a){
super.onCreate(a);
//do some stuff.
task.execute();
progressBar.setVisibility(View.VISIBLE);
}
public void onArticleFetched(Object article){
progressBar.setVisibility(View.GONE);
//updateUI
}
}
You have published drawable instead of layout xml. I haven't any guess how it can be used for indicating progress.
Please check AsyncTask reference. AsyncTask.doInBackground() should be used for obtaining data (networking, parsing and other stuff prohibited in the UI thread). There you time to time need to call AsyncTask.publishProgress() and after that system calls AsyncTask.onProgressUpdate() in the UI thread. Override AsyncTask.onProgressUpdate() to show progress in your UI (set level to progress bar or something else).
At the end AsyncTask.onPostExecute() will be called in the UI thread. Override this method to show data processed in AsyncTask.doInBackground() and modify views as much as you wish.
For a few days a have some problem.
I need to show simple ProgressBar (not dialog) while doing some stuff in main thread...
I thought its a very simple question, but i cant do this, help me please.
First i tried simple setVisibility(View.VISIBLE) before and setVisibility(View.GONE) after.
But this is doing in the same thread, and ProgressBar freezed while my function working.
Now i have this code, but i have some error, and i dont know whats wrong..
my simple layout :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ProgressBar
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
i have a base activity :
public class BaseActivity extends Activity {
public ProgressBar loading;
public class ProgressBarShow extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... unused) {
return(null);
}
protected void onProgressUpdate() {
}
protected void onPreExecute() {
loading.setVisibility(View.VISIBLE);
}
protected void onPostExecute() {
}
}
}
and finally my working activity , which extends BaseActivity
public class SearchActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loading = (ProgressBar) findViewById(R.id.loading);
new ProgressBarShow().execute();
//doing long stuff
//new ProgressBarHide().execute(); there isnt, but sense the same
}
}
I have many activities, which need progress bar, thats why i have created BaseActivity,
to not to dublicate code.
I need to do long work (stuff function) in main thread, because i want to freeze main window and not to allow user do anything (click button etc..), just show working ProgressBar.
Whats wrong in my example? Or give me some advice how can i do this better
class ProgressTask extends AsyncTask<Integer, Integer, Void>{
ProgressBar progress;
Context context;
public ProgressTask(ProgressBar progress, Context context) {
this.progress = progress;
this.context = context;
}
#Override
protected void onPreExecute() {
// initialize the progress bar
// set maximum progress to 100.
progress.setMax(100);
}
#Override
protected Void doInBackground(Integer... params) {
// get the initial starting value
int start=params[0];
// increment the progress
for(int i=start;i<=100;i+=5){
try {
boolean cancelled=isCancelled();
//if async task is not cancelled, update the progress
if(!cancelled){
publishProgress(i);
SystemClock.sleep(1000);
}
} catch (Exception e) {
Log.e("Error", e.toString());
}
}
return null;
}
//Has direct connection to UI Main thread
//Called everytime publishProgress(int) is called in doInBackground
#Override
protected void onProgressUpdate(Integer... values) {
progress.setProgress(values[0]);
Toast.makeText(context, "test"+values[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute(Void result) {
// async task finished
Log.v("Progress", "Finished");
}
#Override
protected void onCancelled() {
progress.setMax(0);
}
}
Use AsyncTask http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html Put your ProgressBar in it, while all work is doing in main thread
In one of my app, I have a scenario where I need to do some background task. For doing that I am using Async Task. Also I am using custom progress dialog. Below is the layout of the custom progress dialog
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:orientation="vertical" >
<ProgressBar
android:layout_width="60dp"
android:layout_height="60dp"
android:indeterminateDrawable="#drawable/progressloader"
android:layout_gravity="center"/>
<TextView
android:id="#+id/progressMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:textSize="18sp"
android:text="Please wait...." />
</LinearLayout>
Everything works fine but when I try to set text to TextView then I am getting java NullPointerException.
AsyncTask code
private class InitialSetup extends AsyncTask<String, Integer, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
}
#Override
protected Long doInBackground(String... urls) {
// txtView.setText("Testing"); here I am getting the error
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
}
MainActivity
public class SummaryActivity extends Activity {
final TextView txtView = (TextView)findbyid(R.id.progressMessage);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.accountsummary);
new InitialSetup().execute("");
}
}
If I understand correctly, your TextView of which you want to set the text can be found in the xml file progressbar.xml (i.e. R.layout.progressbar). This TextView can be obtained once the content view has been set (using setContentView()). In your code you set it before this call is been and the code of mussharapp, he is calling it to early. Namely, he calls it after the setContentView(R.layout.accountsummary) call which does not contain the TextView. Consequently, the variable txtView will be NULL and you will get a NullPointerException.
What you should do is the following:
Set the variable txtView in onPreExecute, after setContentView is called.
Based on Paresh Mayani's explanation: Use the runOnUiThread method.
For the code look down below:
private class InitialSetup extends AsyncTask<String, Integer, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
// The variable is moved here, we only need it here while displaying the
// progress dialog.
TextView txtView;
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
// Set the variable txtView here, after setContentView on the dialog
// has been called! use dialog.findViewById().
txtView = dialog.findViewById(R.id.progressMessage);
}
#Override
protected Long doInBackground(String... urls) {
// Already suggested by Paresh Mayani:
// Use the runOnUiThread method.
// See his explanation.
runOnUiThread(new Runnable() {
#Override
public void run() {
txtView.setText("Testing");
}
});
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
}
Yes, because you are trying to set the TextView inside the doInBackground() method, and this is not allowed,
Why not allowed? Because There is a only one Thread running which is UI Main Thread, and it doesn't allowed to update UI from thread process. read more info here: Painless Threading
So there is a solution if you want to set the TextView inside the doInBackground() method, do the UI updating operations inside the runOnUiThread method.
Otherwise, suggestion is to do all the UI display/update related operations inside the onPostExecute() method instead of doInBackground() method of your AsyncTask class.
(TextView)findViewByid(R.id.progressMessage);
should only be executed after the command setContentView().
TextView txtView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.accountsummary);
**txtView = (TextView)findbyid(R.id.progressMessage);**
new InitialSetup().execute("");
}
Also you can only change UI elements in the main UI thread. doInBackground() is not in the main UI thread. Make UI changes in onPostExecute
public class InitialSetup extends AsyncTask<String, Integer, Long> {
private Activity activity;
ProgressDialog progressDialog;
public InitialSetup(Activity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage("Starting task....");
progressDialog.show();
}
#Override
protected Long doInBackground(String... urls) {
// do something
//
return 0;
}
#Override
protected void onPostExecute(Long result) {
progressDialog.dismiss();
//Perform all UI changes here
**textView.setText("Text#2");**
}
}
The explanations are correct: You are not to make UI changes in any thread except the thread which create the UI. But AsyncTask has a method called
onProgressUpdate()
which always will run in the UI Thread. So based on the modifications by dennisg your code should look like this:
private class InitialSetup extends AsyncTask<String, String, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
// The variable is moved here, we only need it here while displaying the
// progress dialog.
TextView txtView;
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
// Set the variable txtView here, after setContentView on the dialog
// has been called! use dialog.findViewById().
txtView = dialog.findViewById(R.id.progressMessage);
}
#Override
protected Long doInBackground(String... urls) {
publishProgress("Testing");
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
#Override
protected void onProgressUpdate(String... update) {
if (update.length > 0)
txtView.setText(update[0]);
}
}
Note that the type of the parameter of onProgressUpdate is the second type given in AsyncTask!
Extra: To make your code more robust you should check if the progress dialog still exists before setting the text.
Firs of all thanks for reading this.
I'm having trouble updating the progress from my custom ProgressBar through an AsyncTask inner class. I'm using 9patch for the background and progress drawables. It just don't update. It stays there all filled like it was in the maxed value, I'm using the onProgressUpdate() to call the invalidate() and update the UI thread.
Here's what it looks like now, it goes visible and just stays there all filled up: http://imageshack.us/photo/my-images/651/mobicashprogressbar.png/
The progressbar should only be
visible after the user concludes the
form.
There's another inner AsyncTask handling the send SMS button that connects with an Web Service.
HERES THE CODE:
public void setTimerProgress(int progress){
progressBar.setProgress(progress);
}
public void updateProgress(){
progressBar.invalidate();
}
public void showProgress(){
progressBar.setVisibility(View.VISIBLE);
}
//Classe auxiliar para controle da progress bar
private class TimerProgress extends AsyncTask<Void, Void, Void>{
private int start;
private final int OTP_TIMEOUT = 900000;
#Override
protected void onPreExecute() {
super.onPreExecute();
showProgress();
start = (int) System.currentTimeMillis();
}
#Override
protected Void doInBackground(Void... param) {
int timer = (int) System.currentTimeMillis() - start;
while (timer <= OTP_TIMEOUT){
setTimerProgress(timer);
timer = (int) System.currentTimeMillis() - start;
publishProgress();
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
updateProgress();
}
}
HERE'S XML:
<ProgressBar
style="#android:style/Widget.ProgressBar.Horizontal"
android:layout_gravity="center_horizontal"
android:visibility="invisible"
android:id="#+id/progress_bar_timer"
android:max="900000"
android:progress="3000"
android:progressDrawable="#drawable/progress_bar"
android:background="#drawable/progress_background"
android:layout_width="fill_parent"
android:layout_height="25dip"
android:layout_marginRight="73sp"
android:layout_marginLeft="70sp">
</ProgressBar>
HERE'S ONE PLACE WHERE I CALL IT
#Override
public void onClick(View v) {
if (v.getId() == R.id.refresh_otp) {
saveParametersForOTP();
if (edtIniPin.getText().length() == pinLengthInt) {
try {
disableEditText(edtIniPin);
disableEditText(edtValue);
edtOTP.setText(Facade.getInstance().nextOTP(Facade.getInstance().getPin(), Facade.getInstance().getValue()));
//Inicia o timer da progressbar
new TimerProgress().execute();
Help? :D
UPDATE:
For test purpuses I've set the OTP_TIMEOUT to 50000, made the following changes to the code and removed the 9patch drawables properties so it would use the native drawables for the bar. It works, however, when I use the images to customize the bar it appears the same old problem is happening. It is static, all filled up like before.
private final int OTP_TIMEOUT = 50000;
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("PROGRESS", "Chegou no PreExecute!");
showProgress();
ENABLE_REFRESH = false;
start = (int) System.currentTimeMillis();
}
#Override
protected Void doInBackground(Void... param) {
int timer = (int) System.currentTimeMillis() - start;
while (timer <= OTP_TIMEOUT){
Log.i("PROGRESS", "Chegou no while!");
setTimerProgress((int)timer);
timer = (int) System.currentTimeMillis() - start;
publishProgress();
if (timer >= OTP_TIMEOUT) {
ENABLE_REFRESH = true;
}
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
Log.i("PROGRESS", "Chegou no Progress Update!");
updateProgress();
}
You need to add a layer-list resource and configure your ProgressBar to use it.
Here an example that I use. Note that in progress_bar.xml progress_bar_progress and progress_bar_background are nine-patch images.
progress_bar.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background" android:drawable="#drawable/progress_bar_background" />
<item android:id="#android:id/progress" >
<clip android:drawable="#drawable/progress_bar_progress" />
</item>
</layer-list>list>
layout snippet:
<ProgressBar
android:layout_width="fill_parent"
android:layout_height="30dp"
android:max="100"
android:progress="50"
android:progressDrawable="#drawable/progress_bar"
android:indeterminateOnly="false" />