can't call class with alertdialog - android

I've got this code to create a alert dialog with clickable links using a textview:
public static class MyOtherAlertDialog {
public static AlertDialog create(Context context) {
final TextView message = new TextView(context);
// i.e.: R.string.dialog_message =>
// "Test this dialog following the link to dtmilano.blogspot.com"
final SpannableString s =
new SpannableString(context.getText(R.string.dialog_about));
Linkify.addLinks(s, Linkify.WEB_URLS);
message.setText(s);
message.setMovementMethod(LinkMovementMethod.getInstance());
return new AlertDialog.Builder(context)
.setTitle(R.string.about)
.setCancelable(true)
.setIcon(android.R.drawable.ic_dialog_info)
.setPositiveButton("ok", null)
.setView(message)
.create();
}
}
But I don't know exactly how to call it,
I've tried:
MyOtherAlertDialog variable = new MyOtherAlertDialog();
variable.create(this);
But without luck, how should I call this class?

What you're looking for is
AlertDialog dialog = MyOtherAlertDialog.create(this);
dialog.show();
This is rather basic java. If you need to ask this question, maybe you should start by learning some basics.

To show the dialog try using this
MyOtherAlertDialog.create(this).show();
Actually the Dialog is created from your code but it is not shown as you are not calling show() method.
And as the create() method is static so you should access it in a static way.

Answer by StinePike and Alejs G is right. Just want to add that you have declared the create method static. Thus, you need to use class name to call that method.
That is why it should be
MyOtherAlertDialog.create(this);
Same concept applies for variables.

Related

Difference between DialogPreference before and after AndroidX

We are currently migrating to Androidx namespace with our Android app project. However I noticed that not only the namespace seems to have changed. For DialogPreference also some interfaces which were using before are now missing
new interfaces: https://developer.android.com/reference/androidx/preference/DialogPreference
old interfaces: https://developer.android.com/reference/kotlin/android/preference/DialogPreference
For example the following methods seem to be missing: onBindDialogView, showDialog, onDialogClosed.
Since we use some of these methods to influence the default behavior of the dialog, it is unclear to me how I should realize this functionality now. For example we are validating the input before closing the dialog, we are saving the value in a database instead of the sharedpreferences and adding some dynamic elements to the dialog.
Has anyone else already encountered this problem and found a solution? Did I miss anything in the documentation? Is there another concept that we can / should use?
It would be possible to use Fragments instead of DialogPreference but for small amounts of content (e.g. a list of tree items, where the user can choose from) this seems to be a lot of overhead for me...
Starting from androidx source files, I've migrated custom classes based on old DialogPreference to new androidx.preference.DialogPreference with the following procedure:
Step 1
The old custom dialog class (e.g. CustomDialogPreference) based on legacy DialogPreference should be split into two separate classes:
One class (e.g. CustomPreference) should extend androidx.preference.DialogPreference and will contain only the code related to preference handling (data management).
Another class (e.g. CustomDialog) should extend androidx.preference.PreferenceDialogFragmentCompat and will contain only the code related to dialog handling (user interface), including onDialogClosed. This class should expose a static method newInstance to return an instance of this class.
Step 2
In the main fragment handling preferences based on PreferenceFragmentCompat the onDisplayPreferenceDialog method should be overridden to show the custom dialog, e.g.:
private static final String DIALOG_FRAGMENT_TAG = "CustomPreference";
#Override
public void onDisplayPreferenceDialog(Preference preference) {
if (getParentFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
return;
}
if (preference instanceof CustomPreference) {
final DialogFragment f = CustomDialog.newInstance(preference.getKey());
f.setTargetFragment(this, 0);
f.show(getParentFragmentManager(), DIALOG_FRAGMENT_TAG);
} else {
super.onDisplayPreferenceDialog(preference);
}
}
Instead of using DialogPreference, you can write your own custom Preference with an AlertDialog.
This may be a workaround for those who don't want to deal with the DialogPreference and PreferenceDialogFragmentCompat.
import android.content.Context;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
public class CustomDialogPreference extends Preference {
private final Context context;
public CustomDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
#Override
protected void onClick() { //what happens when clicked on the preference
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("TITLE")
.setMessage("message")
.setPositiveButton("OK", (dialog, which) -> {
String preferenceKey = getKey(); //You can update the SharedPreference with the key
//....
})
.setNegativeButton("CANCEL", (dialog, which) -> {
//....
})
.create().show();
}
}
onClick() and getKey() methods belong to the Preference class. The context object comes with the constructor and so on..
The key can be defined, as other preferences, in xml file or programmatically in the PreferenceFragment.
<com.myApp.CustomDialogPreference
android:key="my_preference_key"
android:summary="..."
android:title="..." />
A little hack for everyone who (like me) do not completely understand how we should combine androidx.preference.DialogPreference and androidx.preference.PreferenceDialogFragmentCompat:
Step 1:
In your DialogFragment's onAttach() method get the value of your desired SharedPreference (get the key either from newInstance() method or just hardcore it inside) and save it as a variable. On the other hand, save your new value in SharedPreference before closing your DialogFragment. By doing so, you have created your "custom Preference".
Step 2:
Create empty androidx.preference.DialogPreference and use it inside your PreferenceScreen. Then combine it with your DialogFragment as described in 2nd step by #Livio:
private static final String DIALOG_FRAGMENT_TAG = "CustomPreference";
#Override
public void onDisplayPreferenceDialog(Preference preference) {
if (getFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
return;
}
if (preference instanceof CustomPreference) {
final DialogFragment f = CustomDialog.newInstance(preference.getKey());
f.setTargetFragment(this, 0);
f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
} else {
super.onDisplayPreferenceDialog(preference);
}
}
By doing so, you will get the same result with only difference that you need to deal with SharedPreference yourself inside your DialogFragment.

Alertdialog isShowing always returns false

public class myActivity extends Activity
{
private static AlertDialog somedialog = null;
protected void onCreate(Bundle savedInstanceState)
{
somedialog = new AlertDialog.Builder(ctx).create();
innerclass = new innerclass();
innerclass.start();
}
private class innerClass extends Thread
{
if (!somedialog.isShowing())
{
runOnUiThread(new Runnable()
{
somedialog.setMessage("test");
somedialog.show();
}
}
}
}
I have this code where I have a dialog which needs to show only if the dialog is not already there. The dialog is only shown by the innerClass. There is no other method which invokes this somedialog object.
I expect the dialog to appear for the first time and to reappear only if the previous dialog has been closed, however I find there are multiple dialogs stacked on.
For some reason the isShowing method is returning false even if the dialog is open.
Any ideas as to why this is happening?
However when this code is executed somedialog.isShowing() is always returning false and hence I get multiple dialogs on top of each other.
You are creating a new instance of AlertDialog every time
new AlertDialog.Builder(ctx).create();
and checking isShowing() before it showing. As a result it always return false.
It's possible there are some issues introduced by your multi-threading, and the value of isShowing() being cached as it is read between threads. I can't see the purpose of innerClass from your example, and would simply remove it. This would also be akin to:
private class innerClass extends Thread {
runOnUiThread(new Runnable() {
if(!someDialog.isShowing()) {
somedialog.setMessage("test");
somedialog.show();
}
}
}
Also, you shouldn't keep a static reference to your AlertDialog - there's no need, it wont play nicely with the lifecycle of your Activity, and it's a memory leak waiting to happen.
Thanks for everyone who tried to help me out in this query. It finally turns out to be silly coding error # midnight. I have multiple runOnUiThreads inside the innerclass thread, in one of them the alert object was being re-created.

Get current activity from Application.Context - MonoAndroid

I am currently developing an application using Xamarin.Forms that will be available on the Android and iOS platforms. When the application is first loaded on device, I check to see if there is an internet connection available on the device. I want to display a dialog box if an internet connection is not available.
Here is the following snippet of code I am using to check the internet on the Xamarin.Forms.ContentPage
if(App.Connectivity.IsNetworkConnectivityAvailable())
{
App.Notification.DisplayLocalNotifications("No Internet", "You need an internet connection to access certain application content");
}
I am using dependency injection to build the appropriate module for handling dialog boxes for each appropriate environment. The Android is throwing the following exception
Android.Views.WindowManagerBadTokenException: Unable to add window --
token null is not for an application Here is the code for the
DisplayLocalNotification method on the Android:
public void DisplayLocalNotification(string title, string content)
{
AlertDialog.Builder builder = new AlertDialog.Builder(Application.Context)
.SetTitle(title)
.SetMessage(content)
.SetCancelable(true)
.SetPositiveButton("OK", (EventHandler<DialogClickEventArgs>) null);
AlertDialog alert = builder.Create();
alert.Show();
var okBtn = alert.GetButton((int)DialogButtonType.Positive);
okBtn.Click += (sender, args) =>
{
alert.Dismiss();
};
}
After doing some research, I need to get pass the current activity to the AlertDialog.Builder constructor instead of the Application.Context. How do I get the current activity object from the application context when you need to the activity outside of the activity context?
Xamarin.Forms Android platform code should assign the current Activity into Forms.Context property. This is the static Forms class and if you debug it you will see that the Forms.Context is an Activity.
public static class Forms
{
public static Context Context { get; }
public static bool IsInitialized { get; }
public static event EventHandler<ViewInitializedEventArgs> ViewInitialized;
public static void Init(Activity activity, Bundle bundle);
}

Using Android AlertDialog

I want to create a single class which I can call when I need to show an AlertDialog with the parameters and son on I want.
The problem is I dont know if that class have to be an Activity... the alertDialog needs an context, but I can send the current one, because what I want is to show the alert on the actual activity (not to create a new one, I want to show the alert on the actual screen). But I cant get it. I get errors sending the context of the actual activity...
Only I get working it when I create that class like an Activity, but with that, the alertDialog appears alone without the actual screen behind.
What Can I do? I don't know if I understand the contexts...
Thanks
Your class does not need to extend anything to produce a dialog. You can try this way to produce a static method that creates a dialog for you.
Make sure when you call your method you use THIS and not getApplicationContext()
MyDialogClass.getDialog(this); //good!
MyDialogClass.getDialog(getApplicationContext()); //results in error
That is likely the cause of your error
Example class:
public class MyDialogClass
{
public static AlertDialog getDialog(Context context)
{
Builder builder = new Builder(context);
builder.setTitle("Title").setMessage("Msg").setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id)
{
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id)
{
}
});
return builder.create();
}
}
AynscTask does not need the Context; and no, it doesn't need to be an activity.
http://developer.android.com/reference/android/os/AsyncTask.html
Anyways, you should be able to get the context anytime with no problems. Just do this:
public class MyApplication extends Application{
private static Context context;
public void onCreate(){
super.onCreate();
context = getApplicationContext();
}
public static Context getAppContext() {
return context;
}
}
Then you can get the context from wherever you want with MyApplication.getAppContext(); and pass it on and it should work.

Creating AlertDialog with Static Methods?

I've completed most of the game I'm attempting to make and throughout the project I've created one particular Activity which also calls a SurfaceView and a Thread. I put an update() method in each of the 3 classes so they each know where the other ones are everytime something changes. Apparently, the only way to do something like this is using static methods... This is fine until a collision occurs in my SurfaceView and I want to tell the Activity what to do. I can relay the information, but then I cannot find a way to make an AlertDialog.
I understand I cannot call showDialog() from a Static method, but I cannot find a way to make a non-static method to call it with and then call that method from a static one. I've been searching for an answer and I've heard something about instantiating the object but I cannot figure out what that means...
If anyone has a good idea to get me around this, please let me know :)
Here is what I used:
public static void messageDialog(Activity a, String title, String message){
AlertDialog.Builder dialog = new AlertDialog.Builder(a);
dialog.setTitle(title);
dialog.setMessage(message);
dialog.setNeutralButton("OK", null);
dialog.create().show();
}
SurfaceView extends View and thus have a getContext() method
To create and show your AlertDialog, you can do the following code inside your SurfaceView
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("title");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
Dialog d = builder.create();
d.show();
This might not work as Activity.showDialog(int) if your activity is restarted (the dialog might simply disappear and you will have to handle state yourself).
Hope this helps

Categories

Resources