Preventing Android dialog from extending activities - java

How can I prevent my dialogs from extending activities?
When I create it in my main activity it doesn't dismiss itself when I click "Okay", which creates a new activity. The new activity that is created extends from the MainActivity.
I am using shared preferences to determine where to send the user when they open the app. I'm not sure if that could be playing into this situation.
I want to prevent the dialogs from extending the MainActivity. It shouldn't be showing up on the other activities that I create.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SharedPreferences sharedPreferences = getSharedPreferences("version", 0);
int savedVersionCode = sharedPreferences.getInt("VersionCode", 0);
int appVershionCode = 0;
try { appVershionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; }
catch (NameNotFoundException nnfe) { Log.w(TAG, "$ Exception because of appVershionCode : " + nnfe); }
if(savedVersionCode == appVershionCode){
// Returning user
Log.d(TAG, "$$ savedVersionCode == appVershionCode");
// Temporary Navigation
final Builder alertDialogBuilder = new Builder(this);
new AlertDialog.Builder(new ContextThemeWrapper(getBaseContext(), android.R.style.Theme_Dialog));
alertDialogBuilder.setTitle("Temporary Navigation");
alertDialogBuilder.setMessage("Go to the new activity.");
alertDialogBuilder.setPositiveButton("Okay", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "$$ onClick");
Intent newactivity = new Intent(MAINACTIVITY.this,NEWACTIVITY.class);
startActivity(newactivity);
dialog.cancel();
}
});
alertDialogBuilder.show();
// End
} else {
// First time visitor
Log.d(TAG, "$$ savedVersionCode != appVershionCode");
// Hide graphics meant for returning users
((Button)findViewById(R.id.Button01)).setVisibility(View.INVISIBLE);
SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
sharedPreferencesEditor.putInt("VersionCode", appVershionCode);
sharedPreferencesEditor.commit();
Builder alertDialogBuilder = new Builder(this);
alertDialogBuilder.setTitle("Welcome");
alertDialogBuilder.setMessage("Click Okay to continue.");
alertDialogBuilder.setNeutralButton("Okay", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "$$ onClick");
Intent leagues = new Intent(MAINACTIVITY.this,NEWACTIVITY.class);
startActivity(leagues);
}
});
alertDialogBuilder.show();
}
}

Try dialog.dismiss() like such:
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "$$ onClick");
Intent newactivity = new Intent(MAINACTIVITY.this,NEWACTIVITY.class);
startActivity(newactivity);
dialog.dismiss();
}

From a little understanding of your code, my suggestion would be keeping a check of when you want dialog to be shown and when you dont. e.g You can use a static boolean flag showDialog, set it true/false in your activity according to the use.
if(savedVersionCode == appVershionCode && showDialog)
if(savedVersionCode == appVershionCode && !showDialog)
Its more over over a programmatic problem with a programmatic solution. This is approach would be just a suggestion. As you are following a singleTon type of structure so you must be sure of methods you want to carry further.
Second approach could be, do not do it this way. The common method you want to implement in your activity is related to SharedPref checking, so why not :
Create a class which extends Activity.
Add your SharedPref related methods in it.
Now you can extend that class to all you activities.
public class commonMethod extends Activity{
public void my_sharedPrefMethod(){
// do some thing with prefs
}
#OverRide
public void onCreate(){
super.onCreate();
// common onCreate code for every activity. Recommend not to change this
// so that you can implement
}
// you can also write other methods onPause(), onDestroy() here too.
{
Now you can extend your classes with this class commonMethod. e.g
public class main extends commonMethod{
#overRide
public void oncreate(){
}
#overRide
public void my_sharedPrefMethod(){
}
public void showMyDialog(){
// this way dialog box would not be shown on every activity but just this one.
}
}

Related

Crash in ViewRootImpl.java line XXX on Android 7 despite catching all Toast related errors [duplicate]

From my main activity, I need to call an inner class and in a method within the class, I need to show AlertDialog. After dismissing it, when the OK button is pressed, forward to Google Play for purchase.
Things work perfectly for most of the times, but for few users it is crashing on builder.show() and I can see "android.view.WindowManager$BadTokenException: Unable to add window" from crash log. Please suggest.
My code is pretty much like this:
public class classname1 extends Activity{
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.<view>);
//call the <className1> class to execute
}
private class classNamename2 extends AsyncTask<String, Void, String>{
protected String doInBackground(String... params) {}
protected void onPostExecute(String result){
if(page.contains("error"))
{
AlertDialog.Builder builder = new AlertDialog.Builder(classname1.this);
builder.setCancelable(true);
builder.setMessage("");
builder.setInverseBackgroundForced(true);
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
dialog.dismiss();
if(!<condition>)
{
try
{
String pl = "";
mHelper.<flow>(<class>.this, SKU, RC_REQUEST,
<listener>, pl);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
});
builder.show();
}
}
}
}
I have also seen the error in another alert where I am not forwarding to any other activity. It's simple like this:
AlertDialog.Builder builder = new AlertDialog.Builder(classname1.this);
builder.setCancelable(true);
//if successful
builder.setMessage(" ");
builder.setInverseBackgroundForced(true);
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
// dialog.dismiss();
}
});
builder.show();
}
android.view.WindowManager$BadTokenException: Unable to add window"
Problem :
This exception occurs when the app is trying to notify the user from
the background thread (AsyncTask) by opening a Dialog.
If you are trying to modify the UI from background thread (usually
from onPostExecute() of AsyncTask) and if the activity enters
finishing stage i.e.) explicitly calling finish(), user pressing home
or back button or activity clean up made by Android then you get this
error.
Reason :
The reason for this exception is that, as the exception message says,
the activity has finished but you are trying to display a dialog with
a context of the finished activity. Since there is no window for the
dialog to display the android runtime throws this exception.
Solution:
Use isFinishing() method which is called by Android to check whether
this activity is in the process of finishing: be it explicit finish()
call or activity clean up made by Android. By using this method it is
very easy to avoid opening dialog from background thread when activity
is finishing.
Also maintain a weak reference for the activity (and not a strong
reference so that activity can be destroyed once not needed) and check
if the activity is not finishing before performing any UI using this
activity reference (i.e. showing a dialog).
eg.
private class chkSubscription extends AsyncTask<String, Void, String>{
private final WeakReference<login> loginActivityWeakRef;
public chkSubscription (login loginActivity) {
super();
this.loginActivityWeakRef= new WeakReference<login >(loginActivity)
}
protected String doInBackground(String... params) {
//web service call
}
protected void onPostExecute(String result) {
if(page.contains("error")) //when not subscribed
{
if (loginActivityWeakRef.get() != null && !loginActivityWeakRef.get().isFinishing()) {
AlertDialog.Builder builder = new AlertDialog.Builder(login.this);
builder.setCancelable(true);
builder.setMessage(sucObject);
builder.setInverseBackgroundForced(true);
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
dialog.dismiss();
}
});
builder.show();
}
}
}
}
Update :
Window Tokens:
As its name implies, a window token is a special type of Binder token
that the window manager uses to uniquely identify a window in the
system. Window tokens are important for security because they make it
impossible for malicious applications to draw on top of the windows of
other applications. The window manager protects against this by
requiring applications to pass their application's window token as
part of each request to add or remove a window. If the tokens don't
match, the window manager rejects the request and throws a
BadTokenException. Without window tokens, this necessary
identification step wouldn't be possible and the window manager
wouldn't be able to protect itself from malicious applications.
 A real-world scenario:
When an application starts up for the first time,
the ActivityManagerService creates a special kind of window token
called an application window token, which uniquely identifies the
application's top-level container window. The activity manager gives
this token to both the application and the window manager, and the
application sends the token to the window manager each time it wants
to add a new window to the screen. This ensures secure interaction
between the application and the window manager (by making it
impossible to add windows on top of other applications), and also
makes it easy for the activity manager to make direct requests to the
window manager.
I had dialog showing function:
void showDialog(){
new AlertDialog.Builder(MyActivity.this)
...
.show();
}
I was getting this error and i just had to check isFinishing() before calling this dialog showing function.
if(!isFinishing())
showDialog();
The possible reason is the context of the alert dialog. You may be finished that activity so its trying to open in that context but which is already closed.
Try changing the context of that dialog to you first activity beacause it won't be finished till the end.
e.g
rather than this.
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
try to use
AlertDialog alertDialog = new AlertDialog.Builder(FirstActivity.getInstance()).create();
first you cannot extend AsyncTask without override doInBackground
second try to create AlterDailog from the builder then call show().
private boolean visible = false;
class chkSubscription extends AsyncTask<String, Void, String>
{
protected void onPostExecute(String result)
{
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setMessage(sucObject);
builder.setInverseBackgroundForced(true);
builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
dialog.dismiss();
}
});
AlertDialog myAlertDialog = builder.create();
if(visible) myAlertDialog.show();
}
#Override
protected String doInBackground(String... arg0)
{
// TODO Auto-generated method stub
return null;
}
}
#Override
protected void onResume()
{
// TODO Auto-generated method stub
super.onResume();
visible = true;
}
#Override
protected void onStop()
{
visible = false;
super.onStop();
}
I am creating Dialog in onCreate and using it with show and hide. For me the root cause was not dismissing onBackPressed, which was finishing the Home activity.
#Override
public void onBackPressed() {
new AlertDialog.Builder(this)
.setTitle("Really Exit?")
.setMessage("Are you sure you want to exit?")
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
Home.this.finish();
return;
}
}).create().show();
I was finishing the Home Activity onBackPressed without closing / dismissing my dialogs.
When I dismissed my dialogs the crash disappeared.
new AlertDialog.Builder(this)
.setTitle("Really Exit?")
.setMessage("Are you sure you want to exit?")
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
networkErrorDialog.dismiss() ;
homeLocationErrorDialog.dismiss() ;
currentLocationErrorDialog.dismiss() ;
Home.this.finish();
return;
}
}).create().show();
I try this it solved.
AlertDialog.Builder builder = new AlertDialog.Builder(
this);
builder.setCancelable(true);
builder.setTitle("Opss!!");
builder.setMessage("You Don't have anough coins to withdraw. ");
builder.setMessage("Please read the Withdraw rules.");
builder.setInverseBackgroundForced(true);
builder.setPositiveButton("OK",
(dialog, which) -> dialog.dismiss());
builder.create().show();
In my case I refactored code and put the creation of the Dialog in a separate class. I only handed over the clicked View because a View contains a context object already. This led to the same error message although all ran on the MainThread.
I then switched to handing over the Activity as well and used its context in the dialog creation
-> Everything works now.
fun showDialogToDeletePhoto(baseActivity: BaseActivity, clickedParent: View, deletePhotoClickedListener: DeletePhotoClickedListener) {
val dialog = AlertDialog.Builder(baseActivity) // <-- here
.setTitle(baseActivity.getString(R.string.alert_delete_picture_dialog_title))
...
}
I , can't format the code snippet properly, sorry :(
I got this error, but mine was coming from the Toasts, not a Dialog.
I have Activity and Fragments in my layout. Code for the Toast was in the Activity class. Fragments gets loaded before the Activity.
I think the Toast code was hit before the Context/Activity finished initializing. I think it was the getApplicationContext() in the command Toast.makeText(getApplicationContext(), "onMenutItemActionCollapse called", Toast.LENGTH_SHORT).show();
Try this :
public class <class> extends Activity{
private AlertDialog.Builder builder;
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.<view>);
builder = new AlertDialog.Builder(<class>.this);
builder.setCancelable(true);
builder.setMessage(<message>);
builder.setInverseBackgroundForced(true);
//call the <className> class to execute
}
private class <className> extends AsyncTask<String, Void, String>{
protected String doInBackground(String... params) {
}
protected void onPostExecute(String result){
if(page.contains("error")) //when not subscribed
{
if(builder!=null){
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
dialog.dismiss();
if(!<condition>)
{
try
{
String pl = "";
mHelper.<flow>(<class>.this, SKU, RC_REQUEST,
<listener>, pl);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
});
builder.show();
}
}
}
}
with this globals variables idea,
I saved MainActivity instance in onCreate();
Android global variable
public class ApplicationController extends Application {
public static MainActivity this_MainActivity;
}
and Open dialog like this. it worked.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Global Var
globals = (ApplicationController) this.getApplication();
globals.this_MainActivity = this;
}
and in a thread, I open dialog like this.
AlertDialog.Builder alert = new AlertDialog.Builder(globals.this_MainActivity);
Open MainActivity
Start a thread.
Open dialog from thread -> work.
Click "Back button" ( onCreate will be called and remove first MainActivity)
New MainActivity will start. ( and save it's instance to globals )
Open dialog from first thread --> it will open and work.
: )

When making an AlertDialog the variables don't appear defined

I'm having problems with my first app (learning android studio as i go), I'm trying to insert a Alert Dialog whenever the user clicks on the list item to make sure he wants to delete the item. However, I can't get it working, here's the code if you need more just ask for it. Oh I'm portugues btw, so don't get confused by the variables.
public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
private EditText tarefasET;
private Button btn;
private ListView tarefasList;
private ArrayList<String> tarefas;
private ArrayAdapter<String> adapt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tarefasET = findViewById(R.id.todoEditText);
btn = findViewById(R.id.addBtn);
tarefasList = findViewById(R.id.lvTarefas);
tarefas = FileHelper.lerData(this);
adapt = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, tarefas);
tarefasList.setAdapter(adapt);
btn.setOnClickListener(this);
tarefasList.setOnItemClickListener(this);
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.addBtn:
String newTarefa = tarefasET.getText().toString();
adapt.add(newTarefa);
tarefasET.setText("");
FileHelper.escreve(tarefas, this);
Toast.makeText(this, "Tarefa Adicionada", Toast.LENGTH_SHORT).show();
break;
}
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int posicao, long id) {
AlertDialog confirmDialog = new AlertDialog.Builder(this)
.setTitle("Confirmação")
.setMessage("De certeza que pretende eliminar a tarefa?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
tarefas.remove(posicao);
adapt.notifyDataSetChanged();
FileHelper.escreve(tarefas, this);
Toast.makeText(this, "Tarefa Eliminada", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
What can i do? The app is suposed to be a to-do list, and i can already add and delete files. But i wanted to make a confirmation dialog when the user decides to delete the item he has to-do. But the code gives me the folowing error when i try and lauch the app to the emulator.
the error i'm getting
I suppose you are trying to reference your activity class via this variable. Use class name before this keyword to get outer reference:
FileHelper.escreve(tarefas, MainActivity.this);
Why the problem appears?
Because of the variable scope. The same rules apply to this keyword. Imagine it as a default final variable defined for you by the language.
In your particular case, this keyword references the instance of DialogInterface.OnClickListener you created. The same issue will appear in case any of the MainActivity class level variables names will clash with a variable name of method level variable defined in onClick:
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ArrayList<String> tarefas = new ArrayList();
ArrayList<String> outerTarefas = MainActivity.this.tarefas; // not just tarefas or this.tarefas
}
}

Show alert dialog from background process in any activity

How to get result of background process in any Activity?
I'm working with OTA update. App handle that in background with handler. When update is done I have to show alert dialog to the user. I can show it in SettingsActivity where I start with OTA but user can be in any other Activity.
private void checkIsUpdated() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mDevice.getDevice().read(GattUUID.LS_DEVICE_INFORMATION, GattUUID.LC_FIRMWARE, new
BleDevice.ReadWriteListener() {
#Override
public void onEvent(ReadWriteEvent e) {
if (e.wasSuccess()) {
if (firmwareVersion.equals(e.data_string())) {
showAlertDialog("OTA update failed", "Device is not updated");
} else {
showAlertDialog("OTA update is successful.\nDevice is updated to new " +
"firmware!", "Device is updated");
}
Log.i("OTA", "Read firmware is new success");
} else {
Log.e("OTA", "Read firmware is new success");
}
}
});
}
}, 30000);
}
AlertDialog code
private void showAlertDialog(String message, String title) {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext, R.style.SwipeDialogLight);
builder.setTitle(title)
.setMessage(message)
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
if (!alert.isShowing()) {
alert.show();
}
}
As #W4R10CK stated, I thought that too. The BroadcastReceiver might not a very good idea. But later, I gave a thought about it and if you call checkIsUpdated function inside a Service and send the Broadcast from it, it might be a feasible solution.
So basically you need a BaseActivity class and in which you need to have a BroadcastReceiver. You need to register it onResume and again unregister it onPause.
And you need to have an abstract method to be overriden in each of your Activity too.
So your BaseActivity may look like this..
public abstract class BaseActivity extends AppCompatActivity {
private final Context context;
public BaseActivity() {
this.context = setContext();
}
protected abstract Context setContext();
#Override
public void onResume() {
super.onResume();
registerBroadcastReceiver();
}
#Override
public void onPause() {
super.onPause();
unRegisterBroadcastReceiver();
}
// Declare your BroadcastReceiver here
private class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
showAlertDialog(context);
}
}
}
As #rogerwar suggested in the comments, the correct approach is a broadcast receiver.
Vogella has a nice tutorial
Since you want to have it in all activities, you can make a base class for all your activities and in this base class you can register the receiver in the onStart and unregister it in the onStop.

How to add data to listview after dialog which was called by notification?

My goal is add data to listView, after push on notification shows dialog, if user press Yes, app will show activity with fragment, and again will display new dialog to add new item. But if I press add, I get:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.app.LoaderManager android.support.v4.app.FragmentActivity.getSupportLoaderManager()' on a null object reference
My dialog to add new item to listview be in MainActivity, but I need to refresh my listview in Fragment, i am using ViewPager.
It seems like my fragment not initialized yet, but dialog at display now. How to implement this solution? One more thing, in my notification I set AutoCancel(true), but notif is still being on screen.
Here is the screen chronology:
Step 1
Step 2
one more image i can't add(
My dialog activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String text = getIntent().getStringExtra("text");
new AlertDialogWrapper.Builder(this)
.setTitle(R.string.title_alert)
.setMessage(R.string.title_alert)
.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(DialogActivity.this, MainActivity.class);
intent.putExtra("notification",true);
intent.putExtra("text",text);
startActivity(intent);
finish();
}
}).show();
}
My method which will cal if user press add item in second dialog
private void showTrackerDialog(TrackersFragment f, final String text,boolean isFromNotif) {
final TrackersFragment trackersFragment = f;
tracker = new Tracker();
MaterialDialog dialog = new MaterialDialog.Builder(this)
.title("New tracker :)")
.customView(R.layout.add_track, true)
.positiveText("ADD")
.positiveColorRes(R.color.primary_light_green)
.negativeText(android.R.string.cancel)
.negativeColorRes(R.color.primary_red)
.callback(new MaterialDialog.ButtonCallback() {
#Override
public void onPositive(MaterialDialog dialog) {
if (hours.getValue() == 0 && minutes.getValue() == 0 && isLimit.isCheck()) {
Toast.makeText(getApplicationContext(), "Please check your the input values!", Toast.LENGTH_SHORT).show();
return;
}
//limited
if ((((hours.getValue() != 0 && minutes.getValue() == 0) || (hours.getValue() == 0 && minutes.getValue() != 0))
|| (hours.getValue()!=0 && minutes.getValue()!=0)) && isLimit.isCheck()) {
try {
hoursToMillis = Long.parseLong(String.valueOf(hours.getValue()));
minutesToMillis = Long.parseLong(String.valueOf(minutes.getValue()));
tracker.setLimitTime((hoursToMillis * 60 * 60 * 1000) + (minutesToMillis * 60 * 1000));
tracker.setName(name.getText().toString());
tracker.setElapsedTime((long) 0);
tracker.setIsFinished(false);
tracker.persist(RemindMe.db);
trackersFragment.updateListView(true,tracker);
return;
} catch (Exception ex) {
ex.printStackTrace();
Toast.makeText(getApplicationContext(), "Something goes wrong :(", Toast.LENGTH_SHORT).show();
return;
}
}
//no limit
if (!isLimit.isCheck()) {
tracker.setLimitTime(0L);
tracker.setName(name.getText().toString());
tracker.setElapsedTime((long) 0);
tracker.setIsFinished(false);
tracker.persist(RemindMe.db);
trackersFragment.updateListView(true,tracker);
}
}
#Override
public void onNegative(MaterialDialog dialog) {
}
}).build();
And here is the NullPointerExeption, getSupportLoaderManager()
public void updateListView(boolean isAdded,Tracker tracker) {
if(isAdded && tracker!=null){
trackerList.add(tracker);
getActivity().getSupportLoaderManager().getLoader(TRACKLOADER_ID).forceLoad();
adapter.swapCursor(Tracker.getAll(db));
}
}
Your problem here isn't trying to add to the list, but understanding the lifecycle. It seems to me that you have not setup the fragment, or possible have crossed paths of which fragment library you are using. Your error says v4.Support.Fragment. Make sure you use that same class everywhere. Even when opening it. (Check your imports. Make sure they are all v4).
Also check that your MainActivity does not extend Activity, but FragmentActivity
After which, If you are trying to notify your app from a notification, your best solution is going to be a BroadcastReceiver.

AlertDialog.Builder show(), crash in click handler

My app opens a new view from the main view with:
Intent ElementsIntent = new Intent(this, ElementList.class);
startActivityForResult(ElementsIntent, 0);
which shows a list of elements and when pushing 1 of these elements a view opens up the same way as before with a new Activity. Inside this view I would like to show a AlertDialog in a button click handler, but when I call show() the app crashes.
I am pretty sure it has got somthing to do with the Context not being correct according to where I try and open the dialog, but I have tried making a static context from the main view, I have tried with element.this, which is the class connected to the activity, and I have tried getApplicationContext, and all of these result in an app crash.
I hope someone can explain what I am doing wrong.
Thanks.
Here is the AlertDialog code which crashes:
public void GoBackClickHandler(View v)
{
AlertDialog.Builder builder = new AlertDialog.Builder(ElementItem.this);
builder.setMessage("Skal ændringer i besvarelse gemmes?")
.setCancelable(false)
.setPositiveButton("Ja", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
if(inputIsValue())
{
UpdateELement task = new UpdateELement();
task.applicationContext = ElementItem.this;
task.execute(1);
}
}
})
.setNegativeButton("Nej", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
If I move this code to the OnCreate, then the alert shows just fine and no app crash. It is only if I place it in a ClickHandler it crashes.
I finally found a soloution to this issue.
I had to save the context of the Activity in a variable in the onCreate method and then use this in the ClickHandler AlertDialog call, then everything works.
Hope this will be of help to someone else with this annoying problem.
public class SplashActivity extends AppCompatActivity implements DialogInterface.OnClickListener {
//Object to hold the listener instance
DialogInterface.OnClickListener listener;
#Override
protected void onCreate(Bundle savedInstanceState) {
//Assign this to listener.
listener = this;
handler.postDelayed(new Runnable() {
#Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(SplashActivity.this);
builder.setTitle("Alert");
builder.setMessage("Alert Message...!");
//Here pass the listener object.
builder.setPositiveButton("OK", SplashActivity.this.listener);
builder.show();
}
});
}
#Override
public void onClick(DialogInterface dialog, int which) {
SplashActivity.this.finish();
}
}

Categories