Get Activity Context within class which extends Application in android - android

Dear Folks,
I am currently working on a android app where I need to show the progress dialog. I need to have a context object for this.
This task I am implementing in the class which extends the application. But every time when I tried to access context object it is showing me the WindowManager.BadTokenException for this line
Dialog dialog=ProgressDialog.show(getApplicationContext(), "Status", "Downloading The master");
Please help me where I am doing wrong
Edit:
Below is my code!
public class FlightStatus extends Application {
private Context context;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
SharedPreferences preference=getSharedPreferences("FlightStatus", 1);
if(preference.getBoolean("firstLaunch", true))
{
try {
Dialog dialog=ProgressDialog.show(getApplicationContext(), "Status!", "Downloading The master!!");
XLSReadHelper excelReader=new XLSReadHelper(getApplicationContext());
//excelReader.readExcelFile(Environment.getExternalStorageDirectory()+"/UHCPAudit/cases.xls");
excelReader.readExcelFile();
Log.d("Excel Operation ", "records read!!");
preference.edit().putBoolean("firstLaunch", false).commit();
dialog.dismiss();
} catch (Exception e) {
// TODO: handle exception
Log.d("Excel Operation ", e.getMessage());
}
}
}
}

It is incorrect to try getting Context inside Application, as no Activity is yet initialized at this stage. Instead show your dialog from Activity/Fragment.
If you are showing the progress dialog from an Activity, use:
Dialog dialog = ProgressDialog.show(MyActivity.this, "Status", "Downloading The master");
If you are showing it from a Fragment, then first add this member to your Fragment class:
private Activity activity;
Then call this in your onCreateView() method:
activity = getActivity();
and finally
Dialog dialog = ProgressDialog.show(activity, "Status", "Downloading The master");

You can use a constructor which takes the Activity as context
public class YourClass extends Application{
private Activity context;
public YourClass(Activity context){
this.context = context;
}
}
And then from your calling Activity:
YourClass yourClass = new YourClass(this);
You can also try to use the ProgressDialog in your Activityitself, in a method which you can call from your custom class:
public void showProgress(){
//Your progress code
}
And in your custom class:
context.showProgress();

Related

How can I show a dialog on another context?

My android app needs to show a dialog after a delay. The problem is that by the time the dialog is displayed, the context may have changed.
How can I solve this problem?
My code right now looks like this:
class UpdateRunnable extends Runnable {
private Context ctx;
UpdateRunnable(Context ctx) {
this.ctx = ctx
}
#Override
public void run() {
//throws exception: "Unable to add window -- token null is not for an application"
AlertDialog.Builder builder = new AlertDialog.Builder(ctx.getApplicationContext());
builder.setTitle("Time to refresh data");
builder.setMessage("Data needs updating");
builder.show();
}
}
class MyAvtivity extends AppCompatActivity {
#override
public void onCreate(...) {
Handler updateHandler = new Handler();
updateHandler.postDelayed(new UpdateRunnable(this), 10000);
//do some stuff
//start another activity
}
}
AlertDialog.Builder doesn't work with ApplicationContext. That is why you are getting a bad token exception.
So you need to make sure that the context of your runnable is your current activity context, or try a different aproach like using a service with the logic of when to show the dialog inside, and make it notify the current activity that it should show the dialog, or use the service to start an activity with a Dialog.Theme instead of using an AlertDialog.
have you tried with ContextWrapper?
private Context ctx;
UpdateRunnable(Activity activity) { this.activity = activity }
#Override public void run() {
if(!activity.isFinishing()){
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Time to refresh data");
builder.setMessage("Data needs updating");
builder.show();
}
}

how to show alert dialog on top of any activity in an application android

I want to display an alert dialog. And this alert dialog is created in one activity. But Problem is i want to display this dialog on top of any activity in an application when i get some response from server
Yes i got the solution....
first i created a class for displaying alert dialog.
upon receiving a response from server calling a method to display alert dialog by passing application context
package io.omoto.omotokairaliapp.Utls;
import android.content.Context;
import android.view.WindowManager;
import com.gitonway.lee.niftymodaldialogeffects.lib.NiftyDialogBuilder;
import io.omoto.omotokairaliapp.Constants.Constants;
/**
* Created by ${venkie} on ${28/1/16}.
*/
public class DisplayRegisteredMessage {
Context context;
private NiftyDialogBuilder dialogBuilder;
public DisplayRegisteredMessage(Context context) {
this.context = context;
}
public void displayMessage() {
if (Constants.FLAG == 1) {
Constants.FLAG = 0;
dialogBuilder = NiftyDialogBuilder.getInstance(context);
dialogBuilder
.withTitle("Response is already registered")
.withMessage("For this Customer we have already taken response Sorry!!");
dialogBuilder.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialogBuilder.show();
} else {
}
}
}
The above code displays alert dialog
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
super.onSuccess(statusCode, headers, response);
Log.e("response page", response.toString());
try {
if (response.getString(Constants.STATUS).equalsIgnoreCase("SUCCESS"))
p7.deleterecord(p7b.getFlowid());
p7.deleteRows();
Constants.FLAG = 1;
DisplayRegisteredMessage displayRegisteredMessage = new DisplayRegisteredMessage(mContext);
displayRegisteredMessage.displayMessage();
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("Page 6", p7b.getFlowid());
}
Create alert dialog in other class (not activity) as shown below code in static method & call this method using UDF.showAlertDialog(activity) where you want to show dialog.
public class UDF {
public static void showAlertDialog(
String warning,
DialogInterface.OnClickListener positiveClickListener,
DialogInterface.OnClickListener negativeClickListener,
Context context) {
AlertDialog.Builder alertdialog = new AlertDialog.Builder(context);
alertdialog.setMessage(warning);
alertdialog.setPositiveButton("Ok", positiveClickListener);
alertdialog.setNegativeButton("Cancel", negativeClickListener);
alertdialog.show();
}
}
Edit : set this
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
and add permission in menifest.xml
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
& pass getApplicationContext() while creating dialog instade of activity or context
Here is a workaround that worked for me:
Suppose you have 4 activities in total:
MainActivity
OtherActivity1
OtherActivity2
OtherActivity3
I had the code for the alert dialog in the MainActivity and I wanted the alert dialog to display in all activities. I did the following:
Make other activities extend the main activity.
public class OtherActivity1 extends MainActivity{
}
public class OtherActivity2 extends MainActivity{
}
public class OtherActivity3 extends MainActivity{
}
In your Main activity, save the context in a variable.
public class MainActivity extends AppCompatActivity{
public static Context contextMain;
#Override
protected void onCreate(Bundle savedInstanceState) {
contextMain = MainActivity.this;
}
}
And wherever you are trying to call your alert dialog in the MainActivity just pass contextMain as the context.
final AlertDialog.Builder dialog = new AlertDialog.Builder(contextMain)

Close Progress dialog from outside an Activity

I am trying to close progress dialog after exception occurred, but my current scenario is not allowing me to.
I have 3 classes:
MainActivity
SecondClass
ThirdClass
From MainActivity I am running a task using AsyncTask and shows a progress dialog, while a task is done in background.
#Override
public void onCreate(Bundle savedInstanceState)
{
// my code ...
BackgroundTask bt = new BackgroundTask();
bt.execute();
}
private class BackgroundTask extends AsyncTask<Void, Void, Void>
{
private ProgressDialog PD;
#Override
protected void onPreExecute()
{
PD = new ProgressDialog(getActivity());
PD.setMessage("Performing background tasks...");
PD.setCancelable(false);
PD.show();
}
#Override
protected Void doInBackground(Void... arg0)
{
// call SecondClass's getMyPhotos method to perform some tasks
// ...
return null;
}
protected void onPostExecute(Void... arg0)
{
Log.i("MainActivity", "--called--");
}
}
My SecondClass is simple Java class with some methods
public class SecondClass
{
// ....
public void getMyPhotos()
{
// from here I call ThirdClass's internetRelatedStuff method
}
}
And lastly in ThirdClass I am doing some internet related stuff in AsyncTask:
public class ThirdClass
{
// ....
public void internetRelatedStuff()
{
try
{
// again some other stuff...
// LoadImage asyncTask
LoadImage loadImg = new LoadImage();
loadImg.execute();
}
catch(Exception e)
{
if(e.getErrorCode() == 34)
{
// if I get an exception here, how am I suppose to close close Progress dialog
// of MainActivity
}
}
}
private class LoadImage extends AsyncTask<.......>
{
// .....
}
}
So in my ThirdClass's try/catch, is it possible if an exception occurred, I can close the Progress dialog which is showing from MainActivity?
Yes, there are multiple ways to do this. you can pass the ProgressDialog object in the MainActivity to the SecondClass's getMyPhotos() method then to the ThirdClass constructor then dismiss the dialog
There are couple of ways you can do this, let me point out two ....
You can pass your dialog from activity to SecondClass and then from SecondClass to third class, and use it there to close the dialog ... You will have define ProgressDialog in both second and thirdclass,
Create a static variable ProgressDialog in Activity and a static function closeDialogs()
where you can close your dialogs and you can call it using static ref. from third class,
I personally like this one ....

error in getting context in Alert Dialog in application class

I am creating an application class to perform some version checks during application launch. Below is my class.
public class MyApp extends Application {
public MyApp() {
}
#Override
public void onCreate() {
super.onCreate();
new checkVersionTask().execute(getApplicationContext)
}
private class checkVersionTask extends AsyncTask<Context, Integer, Long> {
#Override
protected Long doInBackground(Context... contexts) {
TODO—version check code
}
protected void onPostExecute(Long result) {
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(MyApp.this).create();
alertDialog.setMessage(("A new version of app is available. Would you like to upgrade now?"));
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, getResources().getString(R.string.Button_Text_Yes), new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
Uri uri = Uri.parse("update URL");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE,getResources().getString(R.string.Button_Text_No), new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
}
catch(Exception e){
Toast.makeText(getApplicationContext(), "ERROR:"+e.toString(), Toast.LENGTH_LONG).show();
}
}
}
}
here alertDialog.show is throwing error
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
As I understand this is because the context is not available. In the line
alertDialog = new AlertDialog.Builder(MyApp.this).create();
I tried getApplicationContext() instead of MyApp.this, still the same issue.
Can anyone suggest what's going wrong here. All the Toast statement are working fine.
You can not create a dialog within an application class since, the Dialog should be attached to a window, an Application is not UI class and has no window, so it can't show the dialog.
you can solve it by creating an activity which will show the dialog (you can pass the data as an extra with the intent), and when the data is ready fire and intent and show the dialog
There are two options for giving your AsyncTask the proper context:
1) Use getBaseContext()
I'm not positive if this will work, it seems to function in some situations rather than others.
2) If THAT doesn't work, you'll need to set up a constructor method for your checkVersionTask, as follows.
Context context; //member variable of the checkVersionTask class
public checkVersionTask(Context c) {
this.context = c;
}
Then, when you call the task in your onCreate method, or anywhere in your activity class for that matter, call it like so
new checkVersionTask(MyApp.this).execute();
Whenever you need to access context within the checkVersionTask, just say, for example
alertDialog = new AlertDialog.Builder(context).create();

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