AsyncTask not receiving calling activity context - android

I'm getting the error message "android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application.
Yes, I know this error is all over stackoverflow and it's based on not getting the context of the activity... however, I am pulling that context and still receiving the error.
From MainActivity:
new MemberStream(this).execute();
From MemberStream:
>
public HomeActivity activity;
ProgressDialog dialog;
public MemberStream(HomeActivity a) {
this.activity = a;
dialog = new ProgressDialog(a.getApplicationContext());
}
#Override
protected void onPreExecute() {
this.dialog.setMessage("Loading");
this.dialog.show();
}
#Override
protected Boolean doInBackground(String... params) {
updateMembers(url, 0);
return true;
}
When I run the application, I get the preceding error on
dialog = new ProgressDialog(a.getApplicationContext());
Any ideas?

public Activity activity;
ProgressDialog dialog;
public MemberStream(Activity a) {
this.activity = a;
dialog = new ProgressDialog(a);
}
You alread have a context object (Your activity)

dialog = new ProgressDialog(a);
You already have a activity context passed to the asynctask constructor.
To know when to use activity context and when to use application context check the link below and answer by commonsware
When to call activity context OR application context?

You can use this
public Context context ;
ProgressDialog dialog;
public MemberStream(Context c) {
context = c;
dialog = new ProgressDialog(c);
}

Related

NullPointerException when trying to show ProgressDialog from a Static AsyncTask method

I have a static AsyncTask in my MainActivity. I run this asynctask to download data from a URL. I'm trying to show a progress dialog from the async task but it crashes on this line: private ProgressDialog dialog = new ProgressDialog(mContext);
I pass the context through to the AsyncTask.
Here is my code:
private static class MyTasksParse extends AsyncTask<String, String, JSONObject> {
private Context mContext;
private ProgressDialog dialog = new ProgressDialog(mContext);
public MyTasksParse(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
this.dialog.setCanceledOnTouchOutside(false);
this.dialog.setMessage("Downloading Files... Please Wait...");
this.dialog.show();
}
#Override
protected JSONObject doInBackground(String... args) {
//get the url and parse it
return json;
}
#Override
protected void onPostExecute(JSONObject json) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
I have tried casting mContext as an Activity as follows:
private ProgressDialog dialog = new ProgressDialog(mContext); but still the same error.
I'm not sure what I'm doing wrong. If anyone can help out, it would be great! Thanks :)
Since you have NullPointerException beacuse the variable mContext is null at this point:
private static class MyTasksParse extends AsyncTask<String, String, JSONObject> {
private Context mContext;
private ProgressDialog dialog = new ProgressDialog(mContext);
...
...
this will help:
private static class MyTasksParse extends AsyncTask<String, String, JSONObject> {
private Context mContext;
private ProgressDialog dialog;
public MyTasksParse(Context context) {
mContext = context;
dialog = new ProgressDialog(mContext)
}
When you receive the value of context in the constructor then you can instatiate correctly the ProgressDialog =).
mContext is null when you pass it to the constructor of ProgressDialog, thus throwing a NullPointerException.
This should work:
private Context mContext;
private ProgressDialog dialog;
public MyTasksParse(Context context) {
mContext = context;
dialog = new ProgressDialog(mContext);
}
The mContext is null when you initialise the ProgressDialog. That's why the crash is happening.
You need to change:
private ProgressDialog dialog = new ProgressDialog(mContext);
to:
private ProgressDialog dialog;
And initialise the progress dialog in onPreExecute:
dialog = new ProgressDialog(mContext);
You are getting NullPointerException beacuse mContext is null.
You need to init ProgressDialog inside constructor like
public MyTasksParse(Context context) {
mContext = context;
dialog = new ProgressDialog(mContext)
}

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

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());

What is the context in Async task

I am running an Async(doInBackground) task in android.
I need to populate a progress bar for the task. So i am showing a progressDialog in onPreExecute,
The signature of ProgressDialog.show is Show(Context,Title,message)
But what would be the Context here?
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(???, "Loading", "Please Wait");
}
Create a constructor for your AsyncTask that takes a context as a parameter.
public class async extends AsyncTask<String, Integer, String>{
private Context context;
public async(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
// Manipulate progress bar
}
Then use this to execute it
async mTask = new async(context).execute(params);
Context can be only of Activity ,Service or Brodcast not of any other class like Asyncktask.So put the Context of that Activity where you are using that AsyncTask class.
You can pass the activity context in the AsyncTask constructor to create the ProgressDialog :
MyAsyncTask constructor :
public MyAsyncTask(Context context){
progressDialog = new ProgressDialog(context, "Loading", "Please wait...");
}
onPreExecute method :
#Override
protected void onPreExecute()
{
progressDialog.show();
}
or store the context and create the dialog in the onPreExecute methods (but I prefer use the first way) :
public class MyAsyncTask extends AsyncTask{
private Context mContext;
public MyAsyncTask(Context context){
this.mContext = context;
}
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(this.mContext, "Loading", "Please Wait");
}
}
And in activity when you declare MyAsyncTask, you pass the activity:
MyAsyncTask asyncTask = new AsyncTask(this);
asynchTask.execute();
Add this function in your class
private Context getDialogContext() {
Context context;
if (getParent() != null)
context = getParent();
else
context = this;
return context;
}
In your asynctask use it as follows
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(getDialogContext(), "Loading", "Please Wait");
}
if you want to use only this as context then your Asynctask should be written as an inner class of a class which extends the Activity class. Then your context is the name of the class which extends Activity. Still it is better practice to pass the context like this:
ClassExtendingActivity.this
you can pass current activity view reference like MainActivity.this

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);
}

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.

Categories

Resources