Android - Having troubles displaying\dismissing a progress dialog while using AsyncTask - android

I'm making a url request using AsyncTask, and want to display some sort of progress spinner while the request is processed. The AsyncTask class is located within another Activity VerificationActivity which extends Activity. The app crashes on this line: dialog = new ProgressDialog(context); Probably the problem is with the context of the app, I tried VerificationActivity.this and creating a local instance of VerificationActivity and passing it as a context.
SmsTask smsTask = new SmsTask(VerificationActivity.this);
/*
* some code
*/
class SmsTask extends AsyncTask<String,Void, Boolean> {
final AtomicBoolean b = new AtomicBoolean(false);
private Context mContext;
ProgressDialog pd;
SmsTask(Context context){
this.mContext = context;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
pd = new ProgressDialog(mContext);
pd.setProgressStyle(AlertDialog.THEME_HOLO_DARK);
pd.show(mContext,"Please wait","Sending...");
}
protected Boolean doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
httpclient.execute(httppost);
b.set(true);
} catch (IOException e) {
e.printStackTrace();
}
return b.get();
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
// result holds what you return from doInBackground
if(pd.isShowing()){
pd.dismiss();
}
Log.i("result from async: ",""+result);
}
}
This is the error message I'm getting:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference
UPDATE:
I fixed the context issue based on the answers here, and ran a test, simulated some heavy work inside the doInBackground method using the Thread.sleep() method, but the progress spinner still doesnt show. Any ideas?
UPDATE2:
I managed to show the progress dialog as i need, but now im not able to dismiss it. I assume it is because I cant dismiss UI elements, do i need to run the progress dialog inside runOnUIThread?

I assume you pass the activity as context and by the time the task is going to be executed, the activity might be gone and the you'll get NullPointerException, so 2 options you have;
Check for the context- of it's null you might not need the loading dialog at all
Use the Application context

Hi please see below the updated AsynTas.
class SmsTask extends AsyncTask<String,Void, Boolean> {
final AtomicBoolean b = new AtomicBoolean(false);
private Context mContext;
private ProgressDialog dialog;
private SmsTask(Context context){
this.mContext = context;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
Log.i("executing Pre - execute","");
dialog = new ProgressDialog(mContext );
dialog.setMessage("Loading...");
dialog.show();
}
protected Boolean doInBackground(String... params) {
//.... dosing stuff
return b.get();
}
#Override
protected void onPostExecute(Boolean result) {
if(dialog.isShowing()){
dialog.dismiss();
}
super.onPostExecute(result);
}
}

private Context context;
you have defined context here, but you didn't initialize it. You can initialize it by a constructor
public SmsTask(Context con){
context = con;
}
and when you call your SmsTask pass context to it.

You need to get the application context -
dialog = new ProgressDialog(getContext());

Related

Very unusual error while dismissing ProgressDialog in AsyncTask

I've developed an Android 2.2 application and I get only one time this error:
java.lang.IllegalArgumentException: View not attached to window manager
This error occur when I dismiss ProgressDialog. This dialog is on an AsyncTask. Here is my code:
private class LoadGatesAsyncTask extends AsyncTask<Void, Void, Boolean>
{
private Context mContext;
private ArrayList<Gate> mGatesList;
private ProgressDialog mLoadingDialog;
public LoadGatesAsyncTask(Context context)
{
this.mContext = context;
mLoadingDialog = new ProgressDialog(mContext);
mLoadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mLoadingDialog.setMessage(getString(R.string.msg_loading_gates));
mLoadingDialog.setCancelable(false);
mLoadingDialog.show();
}
#SuppressWarnings("unchecked")
#Override
protected Boolean doInBackground(Void... params)
{
Boolean result = false;
try
{
[ ... ]
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(Boolean result)
{
super.onPostExecute(result);
if (result)
{
[ ... ]
mLoadingDialog.dismiss();
}
else
{
mLoadingDialog.dismiss();
Toast toast = Toast.makeText(mContext,
getString(R.string.msg_error_loading_gates),
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER,
toast.getXOffset() / 2,
toast.getYOffset() / 2);
toast.show();
}
}
}
How can avoid this error programmatically? Is there any check that I could do to avoid dismiss it if it isn't attached to window manager?
are you instantiating LoadGatesAsyncTask in OnCreate?
If so move the loadingDialog instantiation to OnPreExecute rather than in the Constructor.
You could add the check:
if(mLoadingDialog.isShowing()){
mLoadingDialog.dismiss();
}
You are initializing this ProgressDialog in constructor, not in onPreExecute() and that is wrong because you are dismissing the ProgressDialog in onPostExecute, you need to do it on the same UI thread.
If you initialize the object - AsynTask, you get your constructor called. So your ProgressDialog will be shown, but you haven't called .execute() on the AsyncTask yet! So when you're trying to dismiss it, the compilator is finding itself on a different Thread.
EDIT: Clarifying misunderstood statement.
I think the real problem is behind the attached Activity behind the progressDialog,
it's changing to a new reference (instance),
So that the progressDialog.OwnerActivity=null (usually when in rotation onCreate is called)
it's solved by attaching the new recreated Activity to the owner : progressDialog.OwnerActivity = myActivity; (it will be passed a local parameter in your class, in the constructor pass it,
like :( here C# android, similar to java.. same idea)
class ProgressDialogAsync: AsyncTask //extends asynctask
{
//used parameters
Activity Activity;
string Title;
string Message;
ProgressDialog AsyncDialog;
public ProgressDialogAsync(Activity Activity, string Title, string Message)
{
this.Title = Title;
this.Message = Message;
this.Activity = Activity;
}
protected override void OnPreExecute()
{
AsyncDialog = new ProgressDialog(Activity);
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params) {
//do background operation
}
protected override void OnPostExecute(Java.Lang.Object result)
{
//do something
AsyncDialog.OwnerActivity = Activity;
AsyncDialog.Dismiss();
base.OnPostExecute(result);
}

AsyncTask not showing the ProgressDialog

I am using an AsyncTask (which I am starting in my main activity) to load some data:
Context context = VehicleTabView.this;
ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading...");
new LoadingVehicles(context, progressDialog).execute(null, null, null);
Here is the AsyncClass:
package com.example.schedule_vehicles;
import com.example.utils.VehicleNames;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
// Showing a ProgressDialog once loading the list of vehicles is completed using an AsyncTask
public class LoadingVehicles extends AsyncTask<Void, Void, Void> {
Context context;
ProgressDialog progressDialog;
public LoadingVehicles(Context context, ProgressDialog progressDialog) {
this.context = context;
this.progressDialog = progressDialog;
}
#Override
protected void onPreExecute() {
progressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
new VehicleNames(context);
return null;
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
The problem that the ProgressDialog is not showing on the screen.
I type Log.d, to see if the program is going through all the phases - onPreExecute, doInBackground, onPostExecute, and it is going through all the phases and doing the job that I need. But the ProgressDialog is not showing. I read a lot of information about this thing and it seems that the PRE and POST execute are started by the main thread, which is blocked by the DOINBACKGROUND method, and this is the reason not to see the ProgressDialog. I tried to find some answer how this is solved - but no success.
If anyone faced this, please share your experience. THANKS a lot!
You're passing the ProgressDialog to the Task, just show() it before you start the AsyncTask, not from within the AsyncTask.
Your code looks good to me. You are correct about your understanding of Asynctask and your use of them also appears correct.
The only thing that I can think of is that you must make sure that you are calling execute() on the UI Thread as well. From the code posted I'm not able to tell what context you are in.
Make sure you can pass in "this" as a context. That will tell you if your on the UI thread or not.
ProgressDialog progressDialog = new ProgressDialog(this);
Try :
ProgressDialog progressDialog = new ProgressDialog([Activity Name].this);
Let me know if this solves the problem or I'll see in depth.
Maybe you are missing the context.
ProgressDialog progressDialog = new ProgressDialog(this);
Normally when creating a ProgressDialog, you use the static method ProgressDialog.show(context, title, message). This will create and show the message and give you back a reference to the dialog.
onPreExecute and onPostExecute are called on the main thread, and are not blocked by the doInBackground, which runs on another thread. onPreExecute is called before doInBackground and onPostExecute is called after.
Here's some example code:
public static class InitializeTask extends MyAsyncTask<String, String, Response<Object>> {
private Activity activity;
private ProgressDialog dialog;
public InitializeTask(Activity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(activity, null, "Initializing...");
}
#Override
protected void onPostExecute(Response<Object> result) {
if (dialog != null && dialog.isShowing())
dialog.dismiss();
}
#Override
protected Response<Object> doInBackground(String... params) {
}
#Override
protected void attach(Activity context) {
this.activity = context;
dialog = ProgressDialog.show(context, null, "Initialize...");
}
#Override
protected void detach() {
if (dialog.isShowing())
dialog.dismiss();
activity = null;
}
}
Attach and detach are my own methods for referencing a cross orientation changes.

ProgressDialog is not shown in the AsyncTask

Document doc = new Obtainer(context, uri).execute().get();
This code in the activity class renders the Obtainer(which extends AsyncTask) which gets the xml document from the url. This is the onPreExecute method:
protected void onPreExecute() {
super.onPreExecute();
System.out.println("Pre execute began");
exception = null;
dialog = new ProgressDialog(context);
dialog.setMessage("Loading started");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
System.out.println("Preexecute end");
dialog.show();
}
context is set in the Constructor:
public Obtainer(Context c, String addr) {
context = c;
address = addr;
}
During the runtime I can see in the console output both "Pre execute began" and "Preexecute end" but the progress dialog is not shown. What is the probleM?
Use this code, it works for me:
class Obtainer extends AsyncTask<Void, Void, Void> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(App.this); // App - your main activity class
dialog.setMessage("Please, wait...");
dialog.show();
}
#Override
protected Void doInBackground(Void... params) {
// ...
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
}
}
And in your main activity class method call
new Obtainer().execute();
What Context are you passing when you create your Obtainer (AsyncTask subclass)?
If you are using the Application context via getApplicationContext(), it can not be used to create a Dialog (or any View for that matter). You need to pass it a Context that can create Views.
"If you're in the habit of using your application context (from a call to getApplicationContext(), for example) in places where you need a Context to create views, it's only a matter of time until you find a case where things don't work quite like you would want or expect."
From: https://plus.google.com/107708120842840792570/posts/VTeRBsAeyTi

Android ProgressDialog context problems

Quick summary: I'm making an application that parses a binary file, stores vertices and their properties, and displays them in openGL. I'm trying to implement a ProgressDialog while it parses, but I'm having considerable trouble. I've tried implementing this in many places, but this is my current setup:
public class PointViewer extends Activity{
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
filePath = extras.getString("file_path");
mGLView = new GLSurfaceView(this);
theRenderer = new OpenGLRenderer();
mGLView.setRenderer(theRenderer);
//Parse the file and set the arrays
theRenderer.setLAS(filePath);
setContentView(mGLView);
}
...
}
The Rendering class...
public class OpenGLRenderer extends Activity implements GLSurfaceView.Renderer {
...
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void setLAS (String fileName){
new ProgressTask(this).execute();
}
...
/*
* The class for the progress dialog
*/
private class ProgressTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
private Context context;
//private List<Message> messages;
public ProgressTask(Context ctx) {
context = ctx;
dialog = new ProgressDialog(context);
}
/** progress dialog to show user that the backup is processing. */
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
this.dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.dialog.show();
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
Toast.makeText(context, "OK", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Error", Toast.LENGTH_LONG).show();
}
}
protected Boolean doInBackground(final String... args) {
try{
ptCloud = new PointCloud(args[0]);
...
dialog.setProgress(percentParsed);
return true;
} catch (Exception e){
Log.e("tag", "error", e);
return false;
}
}
}
When I call dialog = new ProgressDialog(context); It errors on a null pointer exception, I'm assuming because there is a context issue... Does anyone have any ideas?
First, you shouldn't create OpenGLRenderer yourself, because its an Activity and is supposed to be managed by system. When you create OpenGLRenderer yourself, then this activity has its context incorrectly initialized. And when your create ProgressDialog with invalid context, you receive NullPointerException.
But even if you start OpenGlRenderer correctly, your app will still crash at line:
dialog.setProgress(percentParsed);
You should use publishProgress instead and update ProgressDialog in AsyncTask's onProgressUpdate function. That's because you can't update UI from non-ui thread.
maybe try replaceing "this" with "OpenGLRenderer.this" inside your setLAS() method. It doesn't seem like it from the code you've posted but sometimes if you are making that call from a different object type it will try to pass in an OnClickListener (or whatever object your calling from) instead of an activity, thus the object has no context. Like I said doesn't seem like that is the case, but worth a shot.
Also where are you calling setLAS() from? perhaps post that section of your code too.
Edit:
Try modifying your setLAS() method to have a Context parameter and pass it in from your first activity, and just pass it along from the second activity to the async task instead of using the context from the second activity.

Fetching data from Internet in background and showing ProgressDialog or ProgressBar

I am developing an application which require accessing a website for
data, and will show that data on device. I wants to fetch data from
Internet in background and show ProgressDialog or ProgressBar on
device and when application receive response from server app will
dismiss the dialog or bar and will show data .
For this i am using AsyncTask -
code for AsyncTask is as follows--
ServerTask extends AsyncTask {
#Override
protected void onPreExecute() {
dialogAccessingServer = new ProgressDialog(ctx);
dialogAccessingServer.setMessage(shownOnProgressDialog);
dialogAccessingSpurstone.show();
}
#Override
protected ServerResponse doInBackground(String... urlArray) {
String urlString = urlArray[0];
HttpResponse serverResponseObject = null;
//finding HttpResponse
return serverResponseObject;
}//end of doInBackground
#Override
protected void onPostExecute(HttpResponse serverResponseObject){
dialogAccessingSpurstone.dismiss();
}
}
and calling this code as follows--
ServerTask serverTaskObject = new ServerTask();
serverTaskObject.execute();
HttpResponse response = serverTaskObject.get();
//performing operation on response
but ProgressDialog is not shown.(I guess the reason for it is the
thread is not complete and android invalidate only when thread has
completed).
My Questions --
1- If my guess is right ? If yes then how I should implement it?
2- If there is any other better way to do this?
thanks
Following is a template code that displays a ProgressDialog while a task is executing in background:
class GetTask extends AsyncTask<Object, Void, String>
{
Context mContext;
ProgressDialog mDialog = null;
GetPhotoFeedTask(Context context)
{
mContext = context;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
mDialog = new ProgressDialog(mContext);
mDialog.setMessage("Please wait...");
mDialog.show();
}
#Override
protected String doInBackground(Object... params)
{
// do stuff in background : fetch response
}
#Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
setProgressBarIndeterminateVisibility(false);
// mDialog.dismiss();
}
}
and you invoke it from your activity using new GetTask(this).execute() statement;
Note: Note that while displaying a ProgressDialog if the user switches the Orientation or causes event that ensues one, the code might break. It is advised to use Managed Dialogs for such cases.
If there is some pending work on UI thread 'Progress dialog' will not appear, so dialog.show() should be the last line on UI thread and any further work should be done in onPostExecute() method.

Categories

Resources