android show alert,popup from non-activity class [duplicate] - android

I have a code which checks some data and shows an alert in a non activity class. But while running application program crashed and does not showing alert dialog. I used below code...
if( str.isEmpty() || strPort.isEmpty()){
new AlertDialog.Builder(Mtx.getContext())
.setMessage("Please provide a valid String")
.setTitle("HAT Alert !!!")
.setCancelable(true)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
return;
}
}).show();
code for Mtx.getContent() method
public class Mtx extends Application {
public static Context context;
#Override
public void onCreate(){
super.onCreate();
Mtx.context = getApplicationContext();
}
public static Context getContext(){
return Mtx.context;
}
}
error message showing in log cat
10-15 12:50:33.708: E/global(329): Deprecated Thread methods are not supported.
10-15 12:50:33.708: E/global(329): java.lang.UnsupportedOperationException
10-15 12:50:33.708: E/global(329): at java.lang.VMThread.stop(VMThread.java:85)
10-15 12:50:33.708: E/global(329): at java.lang.Thread.stop(Thread.java:1280)
10-15 12:50:33.708: E/global(329): at java.lang.Thread.stop(Thread.java:1247)
10-15 12:50:33.708: E/global(329): at mediatronix.HAT.Splash$1.run(Splash.java:36)
please correct me
thanks

Are you sure, the dialog is the problem? What is at line 36 of your Splash.java file? Because according to the stacktrace, there's the problem.

You simply cannot show an AlertDialog using application's context. Dialogs are supposed to attached to an activity's window using its context and stay alive inside its life-cycle. Therefore, you simply need to provide an activity's context which will then allow you to show a Dialog.
As an alternate, I would suggest you to show an Activity themed as dialog using android:theme="#android:style/Theme.Dialog" in your AndroidManifest.xml. This will serve the purpose of manipulating a dialog but in real it will be an activity. As an advantage, you can launch your activities anywhere in your code as long as you have access to application's context.
For more info, read this answer.

When you create the Non Activity class in your Activity, pass the context to its constructor:
NonActivityClass nonActivityClass = new NonActivityClass(this);
Non Activity constructor:
Context mContext;
public NonActivityClass(Context context){
mContext = context;
}
then use:
new AlertDialog.Builder(mContext)... in the Non Activity class

My guess is that your context is null...
Can't you send down a context, to the "codes which checks some data" before starting to checking the data, instead of trying to fetch a context that doesn't exists?
Else make a activity that makes the alertdialog instead, and then startup that activity from your "service" class.

Related

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.

How do I overcome this static vs. non-static method runaround?

I've used this quick-and-dirty msgbox (long live VB) routine extensively with Swing, for both debugging and user info messages:
public static void msgbox(String s){
javax.swing.JOptionPane.showMessageDialog(null, s);
}
I'm just beginning to learn about Android app development. I found Toast in my textbook as being a quick-but-awkward way to show info to the user. Here's the book's code:
String selected="...whatever...";
Toast toast=Toast.makeText(getApplicationContext(),selected,Toast.LENGTH_SHORT);
toast.show();
So I wrote this:
public void msgbox(String message)
{
android.widget.Toast.makeText(getApplicationContext(),
message,
android.widget.Toast.LENGTH_SHORT)
.show();
}
It worked the first time I used it when I only had one class, MainActivity. Then I tried to use it with a Fragment as follows:
public class FragmentA extends Fragment {
public View onCreateView(LayoutInflater
inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_a, container, false);
MainActivity.msgbox("Fragment A"); // **********************************
Button button = (Button) v.findViewById(R.id.button1);
//...
return v;
}
}
The error on the msgbox line is Non-static method msgbox cannot be referenced from a static context.
So I added static to the declaration for msgbox, which seemed like a good idea since that's how my Swing version of msgbox is declared:
public static void msgbox(String message)
{
android.widget.Toast.makeText(getApplicationContext(), // ********************
message,
android.widget.Toast.LENGTH_SHORT).show();
}
That makes the original error go away, but it's replaced by Non-static method getApplicationContext cannot be referenced from a static context.
To fix that error, I changed the declaration for msgbox to include a Context:
public static void msgbox(Context c, String message)
{
android.widget.Toast.makeText(c, message, android.widget.Toast.LENGTH_SHORT)
.show();
}
That works and makes perfect sense, but my quick-and-dirty string-parameter-only call to msgbox has now vanished. I now have to call msgbox like this from main ...
msgbox(getApplicationContext(), "onCreate; about to show fragment A");
... and like this from a separate class: ...
MainActivity.msgbox(getActivity(), "Fragment A");
I tried passing null to Context, which works with Swing JOptionDialog, but I get null pointer exception with makeText, whose first parameter (I thus found out) is documented as #NonNull.
Is there a method other than getApplicationContext and getActivity that I could use as the first parameter to makeText that would allow me to make msgbox static?
Or do I just have to suffer through supplying a Context parameter?
On the other hand, since it possible to do so with Swing, does anybody have a static one-String-parameter msgbox-type method to share? It doesn't have to use makeText.
(I struggled a long time to get as comfortable as I thought I was with Java. Android is every bit as daunting and is making me question what the heck I know ....)
I haven't tried this, but consider subclassing Application, and have it construct a static 'singleton object', giving it the application context. Then put your 'msgbox' method in the singleton.
Context is an extremely important concept in Android. I suggest you read up on it.
To answer the question, I would highly recommend you put that method to make the Toast in your Fragment. Use getActivity() for your context. If you want, you could make a static method in a Utils class that takes Context as a parameter. Then, access it from your Activity or your Fragment and just pass in this or getActivity(), respectively.

Managing activity from DialogFragment

How can I call finish() and other non static methods from a DialogFragment in the activity that created it? I have tried passing messages from the OnClickLisener in the DialogFragment, to no avail.
I have a really simple app, conssting of a MainActivity and DialogFragment:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity);
showDialog();
}
public void showDialog() {
DialogFragment newFragment = new ConfirmDialog();
newFragment.show(getFragmentManager(), "dialog");
}
}
And the Dialog is again very simple:
public class ConfirmDialog extends DialogFragment {
#Override
public AlertDialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Confirm you want to continue?")
.setPositiveButton("Yes.", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//finish() MainActvity
}
})
.setNegativeButton("No.", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//Do nothing in MainActity
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
There are many options. One of them is define an interface with a single method inside.
Have the dialog caller implement that interface.
Keep a global variable pointing to the caller.
Set the variable in the onAttach(Activity activity) method.
Null that variable in the onDetach() method.
Call the variable (interface member) method in the onClick.
Example:
public class MainActivity extends Activity implements MyInterface {
// ...
#Override
public void onChoose() { finish(); }
}
And inside ConfirmDialog:
public static interface MyInterface {
public void onChoose();
}
private MyInterface mListener;
#Override
public void onAttach(Activity activity) {
mListener = (MyInterface) activity;
super.onAttach(activity);
}
#Override
public void onDetach() {
mListener = null;
super.onDetach();
}
And then call mListener.onChoose() anywhere inside your class.
I know this has been marked as accepted, but I figured I could provide more feedback to the discussion.
A note about using or not interfaces. Andy's answer works just as right as mine, hence why I said "There are many options. One of them is...".
However, the reason why I prefer interfaces for this particular problem is because most of the times you're going to extend and reuse simple/common confirmation dialogs like that. hey are too generic to be "wasted" (or worse: duplicated if different event actions arise).
Unless you are deadly sure that you are going to use that only once, for one purpose (finishing), you generally should avoid hardwiring (and simplifying) the implementation details of the Activity in your dialog class. Flexibility, abstraction and efficiency. Less code to maintain.
And yes, there is a telltale that you may need that: the public keyword that you're using, especially if it's in a self-contained class file, which begs for reuse (too). Otherwise, you should be hiding that class inside your main Activity, since the implementation details (would) relate only to that one. Also, you would be removing the public keyword.
Yes, you could use for more than one Activity, but you'd be limited to finish()ing. The interface will give you flexibility to do whatever you want in each Activity. In other words, it's up to the implementer to define how it should itself behave for that event. You self-contain implementation details.
As a sidenote, what I do is create a package with all dialogs I may need for my application. For confirmation dialogs like that, I reuse for different messages and buttons. I provide defaults, but also allow for change using setArguments. And I keep the interfaces related so I don't need to create one interface for each dialog. The implementer responds according to which dialog triggered the "dialogs callback". Flexibility, abstraction and efficiency, all while avoiding things humorously called Hydra and Royal Family. So. In the end, like I said, many options. Don't over-engineer, but don't simplify too much too early (leave room for graceful expansion).
It's more important to understand advantages and pitfalls than choosing this or the other answer.
Even though the amount of work involved to make the interface is small, I don't see why you need to call finish() from the Activity that created it. Calling finish() from within the DialogFragment itself will suffice. If you need to send info back with it as well for some reason, you could always call getActivity() and chain a method that exists in the Activity. Ultimately no matter where you call finish, it will detach the Fragment and destroy it.
Just to clarify how to call a method from your Activity in your Fragment
((YourActivity)getActivity()).someMethod(param);
You MUST caste it because Java doesn't know that Activity has whatever method you wanna call. Which ever way you decide to go with, good luck :)
cheers
EDIT
I appreciate your clarification David. In general you are correct. But to be honest in this instance, you are incorrect because of the nature of Fragments and their relationships with the Activity. Again, you will essentially be creating a listener in order to be called by a Fragment that already has an extremely close relationship with the Activity class it is being held by. Any benefits provided by not hardwiring anything through listeners is lost in this case. You will still be rewriting custom code for every Dialog. While in my method you can write a method in the Activity class in such a general way that you only ever have to write it once.
There are only two reasons I see a need to use a Listener:
1. If you are writing code that other people will be using. So you provide an easy way to give info while maintaining a certain structure (like Androids DatePickerDialog).
2. If there is no connection between two parts you are trying to maintain connected (like GUI's in Java).
So I am not trying to say that David is wrong in saying this, and I am grateful he is bringing it up because it is important for people to understand when to use them. But again, in this case the benefits he mentions are non-existent due to the connection between Fragments and the Activity class. Just wanted to clarify why I believe listeners are not necessary here.
Instead of:
.setPositiveButton("Yes.", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//finish() MainActvity
}
})
Use:
.setPositiveButton("Yes.", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// this gets the current activity.
Activity currentActivity = getActivity();
// this finish() method ends the current activity.
currentActivity.finish();
}
})

Alert Dialog in non activity class

I have a code which checks some data and shows an alert in a non activity class. But while running application program crashed and does not showing alert dialog. I used below code...
if( str.isEmpty() || strPort.isEmpty()){
new AlertDialog.Builder(Mtx.getContext())
.setMessage("Please provide a valid String")
.setTitle("HAT Alert !!!")
.setCancelable(true)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
return;
}
}).show();
code for Mtx.getContent() method
public class Mtx extends Application {
public static Context context;
#Override
public void onCreate(){
super.onCreate();
Mtx.context = getApplicationContext();
}
public static Context getContext(){
return Mtx.context;
}
}
error message showing in log cat
10-15 12:50:33.708: E/global(329): Deprecated Thread methods are not supported.
10-15 12:50:33.708: E/global(329): java.lang.UnsupportedOperationException
10-15 12:50:33.708: E/global(329): at java.lang.VMThread.stop(VMThread.java:85)
10-15 12:50:33.708: E/global(329): at java.lang.Thread.stop(Thread.java:1280)
10-15 12:50:33.708: E/global(329): at java.lang.Thread.stop(Thread.java:1247)
10-15 12:50:33.708: E/global(329): at mediatronix.HAT.Splash$1.run(Splash.java:36)
please correct me
thanks
Are you sure, the dialog is the problem? What is at line 36 of your Splash.java file? Because according to the stacktrace, there's the problem.
You simply cannot show an AlertDialog using application's context. Dialogs are supposed to attached to an activity's window using its context and stay alive inside its life-cycle. Therefore, you simply need to provide an activity's context which will then allow you to show a Dialog.
As an alternate, I would suggest you to show an Activity themed as dialog using android:theme="#android:style/Theme.Dialog" in your AndroidManifest.xml. This will serve the purpose of manipulating a dialog but in real it will be an activity. As an advantage, you can launch your activities anywhere in your code as long as you have access to application's context.
For more info, read this answer.
When you create the Non Activity class in your Activity, pass the context to its constructor:
NonActivityClass nonActivityClass = new NonActivityClass(this);
Non Activity constructor:
Context mContext;
public NonActivityClass(Context context){
mContext = context;
}
then use:
new AlertDialog.Builder(mContext)... in the Non Activity class
My guess is that your context is null...
Can't you send down a context, to the "codes which checks some data" before starting to checking the data, instead of trying to fetch a context that doesn't exists?
Else make a activity that makes the alertdialog instead, and then startup that activity from your "service" class.

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